"Fossies" - the Fresh Open Source Software Archive

Member "openvpn-2.4.7/sample/sample-plugins/keying-material-exporter-demo/keyingmaterialexporter.c" (20 Feb 2019, 7612 Bytes) of package /windows/misc/openvpn-2.4.7.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "keyingmaterialexporter.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.4.4_vs_2.4.5.

    1 /*
    2  *  OpenVPN -- An application to securely tunnel IP networks
    3  *             over a single TCP/UDP port, with support for SSL/TLS-based
    4  *             session authentication and key exchange,
    5  *             packet encryption, packet authentication, and
    6  *             packet compression.
    7  *
    8  *  Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
    9  *
   10  *  This program is free software; you can redistribute it and/or modify
   11  *  it under the terms of the GNU General Public License version 2
   12  *  as published by the Free Software Foundation.
   13  *
   14  *  This program is distributed in the hope that it will be useful,
   15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  *  GNU General Public License for more details.
   18  *
   19  *  You should have received a copy of the GNU General Public License along
   20  *  with this program; if not, write to the Free Software Foundation, Inc.,
   21  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   22  */
   23 
   24 /*
   25  * This file implements a Sample (HTTP) SSO OpenVPN plugin module
   26  *
   27  * See the README file for build instructions.
   28  */
   29 
   30 #define ENABLE_CRYPTO
   31 
   32 #include <stdio.h>
   33 #include <string.h>
   34 #include <stdlib.h>
   35 
   36 #include "openvpn-plugin.h"
   37 
   38 #ifndef MAXPATH
   39 #define MAXPATH 1024
   40 #endif
   41 
   42 #define ovpn_err(fmt, ...) \
   43     plugin->log(PLOG_ERR,   "SSO", fmt, ## __VA_ARGS__)
   44 #define ovpn_dbg(fmt, ...) \
   45     plugin->log(PLOG_DEBUG, "SSO", fmt, ## __VA_ARGS__)
   46 #define ovpn_note(fmt, ...) \
   47     plugin->log(PLOG_NOTE,  "SSO", fmt, ## __VA_ARGS__)
   48 
   49 enum endpoint { CLIENT = 1, SERVER = 2 };
   50 
   51 struct plugin {
   52     plugin_log_t log;
   53     enum endpoint type;
   54     int mask;
   55 };
   56 
   57 struct session {
   58     char user[48];
   59     char key [48];
   60 };
   61 
   62 /*
   63  * Given an environmental variable name, search
   64  * the envp array for its value, returning it
   65  * if found or NULL otherwise.
   66  */
   67 
   68 static const char *
   69 get_env(const char *name, const char *envp[])
   70 {
   71     if (envp)
   72     {
   73         int i;
   74         const int namelen = strlen(name);
   75         for (i = 0; envp[i]; ++i)
   76         {
   77             if (!strncmp(envp[i], name, namelen))
   78             {
   79                 const char *cp = envp[i] + namelen;
   80                 if (*cp == '=')
   81                 {
   82                     return cp + 1;
   83                 }
   84             }
   85         }
   86     }
   87     return NULL;
   88 }
   89 
   90 OPENVPN_EXPORT int
   91 openvpn_plugin_open_v3(const int version,
   92                        struct openvpn_plugin_args_open_in const *args,
   93                        struct openvpn_plugin_args_open_return *rv)
   94 {
   95     struct plugin *plugin = calloc(1, sizeof(*plugin));
   96 
   97     plugin->type = get_env("remote_1", args->envp) ? CLIENT : SERVER;
   98     plugin->log  = args->callbacks->plugin_log;
   99 
  100     plugin->mask  = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL);
  101     plugin->mask |= OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY);
  102 
  103     ovpn_note("vpn endpoint type=%s",plugin->type == CLIENT ? "client" : "server");
  104 
  105     rv->type_mask = plugin->mask;
  106     rv->handle = (void *)plugin;
  107 
  108     return OPENVPN_PLUGIN_FUNC_SUCCESS;
  109 }
  110 
  111 static void
  112 session_user_set(struct session *sess, X509 *x509)
  113 {
  114     int fn_nid;
  115     ASN1_OBJECT *fn;
  116     ASN1_STRING *val;
  117     X509_NAME *x509_name;
  118     X509_NAME_ENTRY *ent;
  119     const char *objbuf;
  120 
  121     x509_name = X509_get_subject_name(x509);
  122     int i, n = X509_NAME_entry_count(x509_name);
  123     for (i = 0; i < n; ++i)
  124     {
  125         if (!(ent = X509_NAME_get_entry(x509_name, i)))
  126         {
  127             continue;
  128         }
  129         if (!(fn = X509_NAME_ENTRY_get_object(ent)))
  130         {
  131             continue;
  132         }
  133         if (!(val = X509_NAME_ENTRY_get_data(ent)))
  134         {
  135             continue;
  136         }
  137         if ((fn_nid = OBJ_obj2nid(fn)) == NID_undef)
  138         {
  139             continue;
  140         }
  141         if (!(objbuf = OBJ_nid2sn(fn_nid)))
  142         {
  143             continue;
  144         }
  145         unsigned char *buf = NULL;
  146         if (ASN1_STRING_to_UTF8(&buf, val) < 0)
  147         {
  148             continue;
  149         }
  150 
  151         if (!strncasecmp(objbuf, "CN", 2))
  152         {
  153             snprintf(sess->user, sizeof(sess->user) - 1, (char *)buf);
  154         }
  155 
  156         OPENSSL_free(buf);
  157     }
  158 }
  159 
  160 static int
  161 tls_verify(struct openvpn_plugin_args_func_in const *args)
  162 {
  163     struct plugin *plugin = (struct plugin  *)args->handle;
  164     struct session *sess  = (struct session *)args->per_client_context;
  165 
  166     /* we store cert subject for the server end point only */
  167     if (plugin->type != SERVER)
  168     {
  169         return OPENVPN_PLUGIN_FUNC_SUCCESS;
  170     }
  171 
  172     if (!args->current_cert)
  173     {
  174         ovpn_err("this example plugin requires client certificate");
  175         return OPENVPN_PLUGIN_FUNC_ERROR;
  176     }
  177 
  178     session_user_set(sess, args->current_cert);
  179 
  180     return OPENVPN_PLUGIN_FUNC_SUCCESS;
  181 }
  182 
  183 static void
  184 file_store(char *file, char *content)
  185 {
  186     FILE *f;
  187     if (!(f = fopen(file, "w+")))
  188     {
  189         return;
  190     }
  191 
  192     fprintf(f, "%s", content);
  193     fclose(f);
  194 }
  195 
  196 static void
  197 server_store(struct openvpn_plugin_args_func_in const *args)
  198 {
  199     struct plugin *plugin = (struct plugin  *)args->handle;
  200     struct session *sess  = (struct session *)args->per_client_context;
  201 
  202     char file[MAXPATH];
  203     snprintf(file, sizeof(file) - 1, "/tmp/openvpn_sso_%s", sess->key);
  204     ovpn_note("app session file: %s", file);
  205     file_store(file, sess->user);
  206 }
  207 
  208 static void
  209 client_store(struct openvpn_plugin_args_func_in const *args)
  210 {
  211     struct plugin *plugin = (struct plugin  *)args->handle;
  212     struct session *sess  = (struct session *)args->per_client_context;
  213 
  214     char *file = "/tmp/openvpn_sso_user";
  215     ovpn_note("app session file: %s", file);
  216     file_store(file, sess->key);
  217 }
  218 
  219 static int
  220 tls_final(struct openvpn_plugin_args_func_in const *args,
  221           struct openvpn_plugin_args_func_return *rv)
  222 {
  223     struct plugin *plugin = (struct plugin  *)args->handle;
  224     struct session *sess  = (struct session *)args->per_client_context;
  225 
  226     const char *key;
  227     if (!(key = get_env("exported_keying_material", args->envp)))
  228     {
  229         return OPENVPN_PLUGIN_FUNC_ERROR;
  230     }
  231 
  232     snprintf(sess->key, sizeof(sess->key) - 1, "%s", key);
  233     ovpn_note("app session key:  %s", sess->key);
  234 
  235     switch (plugin->type) {
  236         case SERVER:
  237             server_store(args);
  238             break;
  239 
  240         case CLIENT:
  241             client_store(args);
  242             return OPENVPN_PLUGIN_FUNC_SUCCESS;
  243     }
  244 
  245     ovpn_note("app session user: %s", sess->user);
  246     return OPENVPN_PLUGIN_FUNC_SUCCESS;
  247 }
  248 
  249 OPENVPN_EXPORT int
  250 openvpn_plugin_func_v3(const int version,
  251                        struct openvpn_plugin_args_func_in const *args,
  252                        struct openvpn_plugin_args_func_return *rv)
  253 {
  254     switch (args->type) {
  255         case OPENVPN_PLUGIN_TLS_VERIFY:
  256             return tls_verify(args);
  257 
  258         case OPENVPN_PLUGIN_TLS_FINAL:
  259             return tls_final(args, rv);
  260     }
  261     return OPENVPN_PLUGIN_FUNC_SUCCESS;
  262 }
  263 
  264 OPENVPN_EXPORT void *
  265 openvpn_plugin_client_constructor_v1(openvpn_plugin_handle_t handle)
  266 {
  267     struct plugin *plugin = (struct plugin *)handle;
  268     struct session *sess  = calloc(1, sizeof(*sess));
  269 
  270     ovpn_note("app session created");
  271 
  272     return (void *)sess;
  273 }
  274 
  275 OPENVPN_EXPORT void
  276 openvpn_plugin_client_destructor_v1(openvpn_plugin_handle_t handle, void *ctx)
  277 {
  278     struct plugin *plugin = (struct plugin *)handle;
  279     struct session *sess  = (struct session *)ctx;
  280 
  281     ovpn_note("app session key: %s", sess->key);
  282     ovpn_note("app session destroyed");
  283 
  284     free(sess);
  285 }
  286 
  287 OPENVPN_EXPORT void
  288 openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
  289 {
  290     struct plugin *plugin = (struct plugin *)handle;
  291     free(plugin);
  292 }