On SSL connections, introduce authentication by client certificate

This commit is contained in:
Sven Geuer 2023-12-11 18:31:42 +01:00
parent a65239015d
commit a425fa20d8
4 changed files with 75 additions and 5 deletions

View file

@ -78,6 +78,10 @@ void cmdline_parser_print_help (void) {
" -F, --passfile=STRING File with credentials for proxy authentication\n"
" -P, --proxyauth=STRING Proxy auth credentials user:pass combination\n"
" -R, --remproxyauth=STRING Remote proxy auth credentials user:pass combination\n"
#ifdef USE_SSL
" -c, --cert=FILENAME client SSL certificate (chain)\n"
" -k, --key=FILENAME client SSL key\n"
#endif
// " -u, --user=STRING Username for proxy authentication\n"
// " -s, --pass=STRING Password for proxy authentication\n"
// " -U, --uservar=STRING Environment variable that holds username\n"
@ -145,6 +149,8 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
args_info->encrypt_given = 0;
args_info->encryptproxy_given = 0;
args_info->encryptremproxy_given = 0;
args_info->clientcert_given = 0;
args_info->clientkey_given = 0;
args_info->wa_bug_29744_given = 0;
args_info->proctitle_given = 0;
args_info->enforcetls1_given = 0;
@ -174,6 +180,8 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
args_info->encrypt_flag = 0; \
args_info->encryptproxy_flag = 0; \
args_info->encryptremproxy_flag = 0; \
args_info->clientcert_arg = NULL; \
args_info->clientkey_arg = NULL; \
args_info->wa_bug_29744_flag = 0; \
args_info->no_ssl3_flag = 0; \
args_info->proctitle_arg = NULL; \
@ -226,6 +234,8 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
{ "encrypt", 0, NULL, 'e' },
{ "encrypt-proxy", 0, NULL, 'E' },
{ "encrypt-remproxy",0,NULL, 'X' },
{ "cert", 1, NULL, 'c' },
{ "key", 1, NULL, 'k' },
{ "wa-bug-29744", 0, NULL, 'W' },
{ "buggy-encrypt-proxy", 0, NULL, 'B' },
{ "no-ssl3", 0, NULL, 'T' },
@ -236,9 +246,9 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
{ NULL, 0, NULL, 0 }
};
c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXWBqLo:TzC:46", long_options, &option_index);
c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:c:k:vNeEXWBqLo:TzC:46", long_options, &option_index);
#else
c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXWBqLo:TzC:46" );
c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:c:k:vNeEXWBqLo:TzC:46" );
#endif
if (c == -1)
@ -263,6 +273,26 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
message("SSL client to proxy enabled\n");
break;
case 'c': /* client SSL certificate (chain) */
if (args_info->clientcert_given) {
fprintf (stderr, "%s: '--cert' ('-c') option given more than once\n", PACKAGE);
clear_args ();
exit(1);
}
args_info->clientcert_given = 1;
args_info->clientcert_arg = gengetopt_strdup (optarg);
break;
case 'k': /* client SSL key */
if (args_info->clientkey_given) {
fprintf (stderr, "%s: '--key' ('-k') option given more than once\n", PACKAGE);
clear_args ();
exit(1);
}
args_info->clientkey_given = 1;
args_info->clientkey_arg = gengetopt_strdup (optarg);
break;
case 'W': /* if SSL is active stop it after CONNECT */
args_info->wa_bug_29744_flag = !(args_info->wa_bug_29744_flag);
if( args_info->verbose_flag )
@ -318,7 +348,7 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
case 'o':
args_info->host_given = 1;
message("Host-header override enabled\n");
message("Host-header/SNI override enabled\n");
args_info->host_arg = gengetopt_strdup (optarg);
break;
@ -585,6 +615,12 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
exit(1);
}
if ( args_info->clientcert_given ^ args_info->clientkey_given ) {
clear_args ();
message( "Both of '--cert' ('-c') and '--key' ('-k') must be specified\n" );
exit(1);
}
if (args_info->proxy_given ) {
char proxy_arg_fmt[32];
size_t proxy_arg_len;

View file

@ -47,6 +47,8 @@ struct gengetopt_args_info {
int encrypt_flag; /* Turn on SSL encryption (default=off). */
int encryptproxy_flag; /* Turn on client to proxy SSL encryption (def=off).*/
int encryptremproxy_flag; /* Turn on local to remote proxy SSL encryption (def=off).*/
char *clientcert_arg; /* client SSL certificate */
char *clientkey_arg; /* client SSL key */
int wa_bug_29744_flag; /* Use SSL encryption only until CONNECT, if at all (def=off).*/
int no_ssl3_flag; /* Turn off SSLv3 (default=on) */
char *proctitle_arg; /* Override process title (default=off). */
@ -78,6 +80,8 @@ struct gengetopt_args_info {
int encrypt_given; /* Whether encrypt was given */
int encryptproxy_given; /* Whether encrypt was given */
int encryptremproxy_given; /* Whether encrypt was given */
int clientcert_given; /* Whether client SSL certificate was given */
int clientkey_given; /* Whether client SSL key was given */
int wa_bug_29744_given; /* Whether work around was given */
int proctitle_given; /* Whether to override process title */
int enforcetls1_given; /* Wheter to enforce TLSv1 */

View file

@ -101,6 +101,24 @@ also be used for other proxy-traversing purposes like proxy bouncing.
If the _password_ is omitted and no *REMPROXYPASS* environment variable is
set, proxytunnel will prompt for a password
*-c*, *--cert*=_filename_::
Provide the name of the file containing the client SSL certificate to
authenticate by client certificate against a local proxy, remote proxy or
the destination. The file must be in PEM format.
On top of this it may contain one or more intermediary certificates missing
at the servers's end, effectively forming a certificate chain.
Requires specification of *-k*, *--key* in addition.
Ignored if neither *-e*, *--encrypt** nor *-E*, *--encrypt-proxy* nor
*-X*, *--encrypt-remproxy* is given.
*-k*, *--key*=_filename_::
Provide the name of the file containing the client SSL key to authenticate
by client certificate against a local proxy, remote proxy or the
destination. The file must be in PEM format.
Requires specification of *-c*, *--cert* in addition.
Ignored if neither *-e*, *--encrypt** nor *-E*, *--encrypt-proxy* nor
*-X*, *--encrypt-remproxy* is given.
*-N*, *--ntlm*::
Use NTLM based authentication
@ -110,8 +128,8 @@ also be used for other proxy-traversing purposes like proxy bouncing.
*-H*, *--header*=_STRING_::
Add additional HTTP headers to send to proxy
*-o*, *--host*=_STRING_::
Send a custom Host Header
*-o*, *--host*=_fully_qualified_domain_name_::
Send a custom Host Header. Also used as SNI with SSL connections.
*-x*, *--proctitle*=_STRING_::
Use a different process title

View file

@ -317,6 +317,18 @@ int stream_enable_ssl(PTSTREAM *pts, const char *proxy_arg) {
}
}
/* If given, load client certificate (chain) and key */
if ( args_info.clientcert_given && args_info.clientkey_given ) {
if ( 1 != SSL_CTX_use_certificate_chain_file(ctx, args_info.clientcert_arg) ) {
message("Error loading client certificate (chain) from %s\n", args_info.clientcert_arg);
goto fail;
}
if ( 1 != SSL_CTX_use_PrivateKey_file(ctx, args_info.clientkey_arg, SSL_FILETYPE_PEM) ) {
message("Error loading client key from %s, or key does not match certificate\n", args_info.clientkey_arg);
goto fail;
}
}
ssl = SSL_new (ctx);
if ( ssl == NULL ) {
message("SSL_new failed\n");