base64.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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) 2017 David Sommerseth <davids@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
  20. * along with this program (see the file COPYING included with this
  21. * distribution); if not, write to the Free Software Foundation, Inc.,
  22. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include "openvpn-plugin.h"
  28. #define PLUGIN_NAME "base64.c"
  29. /* Exported plug-in v3 API functions */
  30. plugin_log_t ovpn_log = NULL; /**< Pointer to the OpenVPN log function. See plugin_log() */
  31. plugin_vlog_t ovpn_vlog = NULL; /**< Pointer to the OpenVPN vlog function. See plugin_vlog() */
  32. plugin_base64_encode_t ovpn_base64_encode = NULL; /**< Pointer to the openvpn_base64_encode () function */
  33. plugin_base64_decode_t ovpn_base64_decode = NULL; /**< Pointer to the openvpn_base64_decode () function */
  34. /**
  35. * Search the environment pointer for a specific env var name
  36. *
  37. * PLEASE NOTE! The result is not valid outside the local
  38. * scope of the calling function. Once the calling function
  39. * returns, any returned pointers are invalid.
  40. *
  41. * @param name String containing the env.var name to search for
  42. * @param envp String array pointer to the environment variable
  43. *
  44. * @return Returns a pointer to the value in the environment variable
  45. * table on successful match. Otherwise NULL is returned
  46. *
  47. */
  48. static const char *
  49. get_env(const char *name, const char *envp[])
  50. {
  51. if (envp)
  52. {
  53. int i;
  54. const int namelen = strlen(name);
  55. for (i = 0; envp[i]; ++i)
  56. {
  57. if (!strncmp(envp[i], name, namelen))
  58. {
  59. const char *cp = envp[i] + namelen;
  60. if (*cp == '=')
  61. {
  62. return cp + 1;
  63. }
  64. }
  65. }
  66. }
  67. return NULL;
  68. }
  69. /**
  70. * This function is called when OpenVPN loads the plug-in.
  71. * The purpose is to initialize the plug-in and tell OpenVPN
  72. * which plug-in hooks this plug-in wants to be involved in
  73. *
  74. * For the arguments, see the include/openvpn-plugin.h file
  75. * for details on the function parameters
  76. *
  77. * @param v3structver An integer containing the API version of
  78. * the plug-in structs OpenVPN uses
  79. * @param args A pointer to the argument struct for
  80. * information and features provided by
  81. * OpenVPN to the plug-in
  82. * @param ret A pointer to the struct OpenVPN uses to
  83. * receive information back from the plug-in
  84. *
  85. * @return Must return OPENVPN_PLUGIN_FUNC_SUCCESS when everything
  86. * completed successfully. Otherwise it must be returned
  87. * OPENVPN_PLUGIN_FUNC_ERROR, which will stop OpenVPN
  88. * from running
  89. *
  90. */
  91. OPENVPN_EXPORT int
  92. openvpn_plugin_open_v3(const int v3structver,
  93. struct openvpn_plugin_args_open_in const *args,
  94. struct openvpn_plugin_args_open_return *ret)
  95. {
  96. /* Check that we are API compatible */
  97. if (v3structver != OPENVPN_PLUGINv3_STRUCTVER)
  98. {
  99. printf("base64.c: ** ERROR ** Incompatible plug-in interface between this plug-in and OpenVPN\n");
  100. return OPENVPN_PLUGIN_FUNC_ERROR;
  101. }
  102. /* Which callbacks to intercept. */
  103. ret->type_mask =
  104. OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY)
  105. |OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT_V2);
  106. /* we don't need a plug-in context in this example, but OpenVPN expects "something" */
  107. ret->handle = calloc(1, 1);
  108. /* Hook into the exported functions from OpenVPN */
  109. ovpn_log = args->callbacks->plugin_log;
  110. ovpn_vlog = args->callbacks->plugin_vlog;
  111. ovpn_base64_encode = args->callbacks->plugin_base64_encode;
  112. ovpn_base64_decode = args->callbacks->plugin_base64_decode;
  113. /* Print some version information about the OpenVPN process using this plug-in */
  114. ovpn_log(PLOG_NOTE, PLUGIN_NAME, "OpenVPN %s (Major: %i, Minor: %i, Patch: %s)\n",
  115. args->ovpn_version, args->ovpn_version_major,
  116. args->ovpn_version_minor, args->ovpn_version_patch);
  117. return OPENVPN_PLUGIN_FUNC_SUCCESS;
  118. }
  119. /**
  120. * This function is called by OpenVPN each time the OpenVPN reaches
  121. * a point where plug-in calls should happen. It only happens for those
  122. * plug-in hooks enabled in openvpn_plugin_open_v3().
  123. *
  124. * For the arguments, see the include/openvpn-plugin.h file
  125. * for details on the function parameters
  126. *
  127. * @param args Pointer to a struct with details about the plug-in
  128. * call from the main OpenVPN process.
  129. * @param returndata Pointer to a struct where the plug-in can provide
  130. * information back to OpenVPN to be processed
  131. *
  132. * @return Must return OPENVPN_PLUGIN_FUNC_SUCCESS or
  133. * OPENVPN_PLUGIN_FUNC_DEFERRED on success. Otherwise it
  134. * should return OPENVPN_FUNC_ERROR, which will stop and reject
  135. * the client session from progressing.
  136. *
  137. */
  138. OPENVPN_EXPORT int
  139. openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
  140. {
  141. if (type != OPENVPN_PLUGIN_TLS_VERIFY
  142. && type != OPENVPN_PLUGIN_CLIENT_CONNECT_V2)
  143. {
  144. ovpn_log(PLOG_ERR, PLUGIN_NAME, "Unsupported plug-in hook call attempted");
  145. return OPENVPN_PLUGIN_FUNC_ERROR;
  146. }
  147. /* get username/password from envp string array */
  148. const char *clcert_cn = get_env("X509_0_CN", envp);
  149. if (!clcert_cn)
  150. {
  151. /* Ignore certificate checks not being a client certificate */
  152. return OPENVPN_PLUGIN_FUNC_SUCCESS;
  153. }
  154. /* test the BASE64 encode function */
  155. char *buf = NULL;
  156. int r = ovpn_base64_encode(clcert_cn, strlen(clcert_cn), &buf);
  157. ovpn_log(PLOG_NOTE, PLUGIN_NAME, "BASE64 encoded '%s' (return value %i): '%s'",
  158. clcert_cn, r, buf);
  159. /* test the BASE64 decode function */
  160. char buf2[256] = {0};
  161. r = ovpn_base64_decode(buf, &buf2, 255);
  162. ovpn_log(PLOG_NOTE, PLUGIN_NAME, "BASE64 decoded '%s' (return value %i): '%s'",
  163. buf, r, buf2);
  164. /* Verify the result, and free the buffer allocated by ovpn_base64_encode() */
  165. r = strcmp(clcert_cn, buf2);
  166. free(buf);
  167. return (r == 0) ? OPENVPN_PLUGIN_FUNC_SUCCESS : OPENVPN_PLUGIN_FUNC_ERROR;
  168. }
  169. /**
  170. * This cleans up the last part of the plug-in, allows it to
  171. * shut down cleanly and release the plug-in global context buffer
  172. *
  173. * @param handle Pointer to the plug-in global context buffer, which
  174. * need to be released by this function
  175. */
  176. OPENVPN_EXPORT void
  177. openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
  178. {
  179. struct plugin_context *context = (struct plugin_context *) handle;
  180. free(context);
  181. }