From: Sam Hartman Date: Mon, 8 Jul 2013 19:08:29 +0000 (-0400) Subject: gsscon: callback for client name validation X-Git-Tag: 1.0~12 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=trust_router.git;a=commitdiff_plain;h=54a1292fad6e8daef53e13fec9250798a03d63da gsscon: callback for client name validation gsscon_passive_authenticate now takes a callback for client authentication. --- diff --git a/gsscon/gsscon_passive.c b/gsscon/gsscon_passive.c index 96d1417..87506fc 100755 --- a/gsscon/gsscon_passive.c +++ b/gsscon/gsscon_passive.c @@ -57,17 +57,22 @@ const char *gServiceName = NULL; int gsscon_passive_authenticate (int inSocket, - gss_ctx_id_t *outGSSContext) + gss_ctx_id_t *outGSSContext, + client_cb_fn clientCb, + void *clientCbData) { int err = 0; OM_uint32 majorStatus; OM_uint32 minorStatus = 0; gss_ctx_id_t gssContext = GSS_C_NO_CONTEXT; + gss_name_t clientName = GSS_C_NO_NAME; + gss_buffer_desc clientDisplayName = {0, NULL}; char *inputTokenBuffer = NULL; size_t inputTokenBufferLength = 0; gss_buffer_desc inputToken; /* buffer received from the server */ + if (inSocket < 0 ) { err = EINVAL; } if (!outGSSContext) { err = EINVAL; } @@ -107,28 +112,16 @@ int gsscon_passive_authenticate (int inSocket, /* * accept_sec_context does the actual work of taking the client's * request and generating an appropriate reply. Note that we pass - * GSS_C_NO_CREDENTIAL for the service principal. This causes the - * server to accept any service principal in the server's keytab, - * which enables you to support multihomed hosts by having one key - * in the keytab for each host identity the server responds on. - * - * However, since we may have more keys in the keytab than we want - * the server to actually use, we will need to check which service - * principal the client used after authentication succeeds. See - * ServicePrincipalIsValidForService() for where you would put these - * checks. We don't check here since if we stopped responding in the - * middle of the authentication negotiation, the client would get an - * EOF, and the user wouldn't know what went wrong. - */ - + * GSS_C_NO_CREDENTIAL for the service principal. + */ // printf ("Calling gss_accept_sec_context...\n"); majorStatus = gss_accept_sec_context (&minorStatus, &gssContext, GSS_C_NO_CREDENTIAL, &inputToken, GSS_C_NO_CHANNEL_BINDINGS, - NULL /* client_name */, - NULL /* actual_mech_type */, + &clientName, + NULL /* actual_mech_type */, &outputToken, NULL /* req_flags */, NULL /* time_rec */, @@ -148,7 +141,17 @@ int gsscon_passive_authenticate (int inSocket, err = minorStatus ? minorStatus : majorStatus; } } - + + if (!err) { + majorStatus = gss_display_name(&minorStatus, clientName, &clientDisplayName, NULL); + if (GSS_ERROR(majorStatus)) { + gsscon_print_gss_errors("gss_display_name", majorStatus, minorStatus); + err = EINVAL; + } + if (!err) + err = clientCb(clientName, &clientDisplayName, clientCbData); + } + if (!err) { *outGSSContext = gssContext; gssContext = NULL; @@ -159,6 +162,10 @@ int gsscon_passive_authenticate (int inSocket, if (inputTokenBuffer) { free (inputTokenBuffer); } if (gssContext != GSS_C_NO_CONTEXT) { gss_delete_sec_context (&minorStatus, &gssContext, GSS_C_NO_BUFFER); } +if (clientName != GSS_C_NO_NAME) + gss_release_name(&minorStatus, &clientName); +if (clientDisplayName.value != NULL) + gss_release_buffer(&minorStatus, &clientDisplayName); return err; } diff --git a/gsscon/test/gsscon_server.c b/gsscon/test/gsscon_server.c index 63b460a..d7d3847 100644 --- a/gsscon/test/gsscon_server.c +++ b/gsscon/test/gsscon_server.c @@ -53,7 +53,20 @@ */ #include +#include +static int cb_print_names(gss_name_t clientName, + gss_buffer_t displayName, + void *data) +{ + assert(clientName != NULL); + assert(data == NULL); + printf("Gss name: %-*s\n", + displayName->length, displayName->value); + return 0; +} + + /* --------------------------------------------------------------------------- */ static int SetupListeningSocket (int inPort, @@ -153,7 +166,8 @@ int main (int argc, const char *argv[]) } printf ("Accepting new connection...\n"); - connectionErr = gsscon_passive_authenticate (connectionFD, &gssContext); + connectionErr = gsscon_passive_authenticate (connectionFD, &gssContext, + cb_print_names, NULL); if (!connectionErr) { connectionErr = gsscon_authorize (gssContext, diff --git a/include/gsscon.h b/include/gsscon.h index f0bfec3..35ff039 100644 --- a/include/gsscon.h +++ b/include/gsscon.h @@ -73,6 +73,10 @@ #define kDefaultPort 2000 extern const char *gServiceName; +typedef int (*client_cb_fn)( + gss_name_t client_name, gss_buffer_t client_display_name, + void *); + int gsscon_read_token (int inSocket, char **outTokenValue, size_t *outTokenLength); @@ -105,7 +109,9 @@ int gsscon_connect (const char *inHost, gss_ctx_id_t *outGSSContext); int gsscon_passive_authenticate (int inSocket, - gss_ctx_id_t *outGSSContext); + gss_ctx_id_t *outGSSContext, + client_cb_fn client_cb, + void *client_cb_data); int gsscon_authorize (gss_ctx_id_t inContext, int *outAuthorized,