From 678fa396433b5b1f545d3b7e05e195bb6611adc6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Kou=C5=99il?= Date: Tue, 31 Jan 2012 13:44:21 +0000 Subject: [PATCH] - return the client's description after successful authentication - added routines to obtain principal's name and to free the structure --- emi.canl.canl-c/src/canl.c | 43 ++++++++++++++++++++++++++++++++++++ emi.canl.canl-c/src/canl.h | 3 +++ emi.canl.canl-c/src/canl_error_codes | 1 + emi.canl.canl-c/src/canl_locl.h | 8 +++++-- emi.canl.canl-c/src/canl_ssl.c | 41 +++++++++++++++++++++++++++++++++- 5 files changed, 93 insertions(+), 3 deletions(-) diff --git a/emi.canl.canl-c/src/canl.c b/emi.canl.canl-c/src/canl.c index ef66074..a09854c 100644 --- a/emi.canl.canl-c/src/canl.c +++ b/emi.canl.canl-c/src/canl.c @@ -272,6 +272,12 @@ canl_io_accept(canl_ctx cc, canl_io_handler io, int new_fd, if (err) goto end; + if (peer) { + err = mech->get_peer(glb_cc, io_cc, conn_ctx, peer); + if (err) + goto end; + } + io_cc->authn_mech.ctx = conn_ctx; io_cc->authn_mech.type = mech->mech; io_cc->authn_mech.oid = GSS_C_NO_OID; @@ -472,3 +478,40 @@ find_mech(gss_OID oid) /* XXX */ return &canl_mech_ssl; } + +canl_err_code +canl_princ_name(canl_ctx cc, const canl_principal princ, char **name) +{ + struct _principal_int *p = (struct _principal_int *) princ; + + if (cc == NULL) + return -1; + if (princ == NULL) + return set_error(cc, EINVAL, POSIX_ERROR, "Principal not initialized"); + + if (name == NULL) + return set_error(cc, EINVAL, POSIX_ERROR, "invalid parameter value"); + + *name = strdup(p->name); + if (*name == NULL) + return set_error(cc, ENOMEM, POSIX_ERROR, "not enough memory"); + + return 0; +} + +void +canl_princ_free(canl_ctx cc, canl_principal princ) +{ + struct _principal_int *p = (struct _principal_int *) princ; + + if (cc == NULL) + return; + if (princ == NULL) + return; + + if (p->name) + free(p->name); + free(princ); + + return; +} diff --git a/emi.canl.canl-c/src/canl.h b/emi.canl.canl-c/src/canl.h index 02ef8a3..5df93f7 100644 --- a/emi.canl.canl-c/src/canl.h +++ b/emi.canl.canl-c/src/canl.h @@ -66,6 +66,9 @@ canl_princ_name(canl_ctx, const canl_principal, char **); canl_err_code CANL_CALLCONV canl_princ_mech(canl_ctx, const canl_principal, gss_OID *); +void CANL_CALLCONV +canl_princ_free(canl_ctx, canl_principal); + char * CANL_CALLCONV canl_mech2str(canl_ctx, gss_OID); diff --git a/emi.canl.canl-c/src/canl_error_codes b/emi.canl.canl-c/src/canl_error_codes index acaf883..7795b38 100644 --- a/emi.canl.canl-c/src/canl_error_codes +++ b/emi.canl.canl-c/src/canl_error_codes @@ -103,3 +103,4 @@ trustPubKeyError GeneralSSLError HostNotFound ResolverError +NoClientCertificate diff --git a/emi.canl.canl-c/src/canl_locl.h b/emi.canl.canl-c/src/canl_locl.h index a15c61f..32c7e79 100644 --- a/emi.canl.canl-c/src/canl_locl.h +++ b/emi.canl.canl-c/src/canl_locl.h @@ -74,8 +74,8 @@ typedef struct _asyn_result { typedef struct _principal_int { char *name; - CANL_AUTH_MECHANISM mech_oid; - char *raw; /* e.g. the PEM encoded cert/chain */ +// CANL_AUTH_MECHANISM mech_oid; +// char *raw; /* e.g. the PEM encoded cert/chain */ } principal_int; typedef struct _io_handler @@ -122,6 +122,10 @@ typedef struct canl_mech { canl_err_code (*write) (glb_ctx *, io_handler *, void *, void *, size_t, struct timeval *); + + canl_err_code (*get_peer) + (glb_ctx *, io_handler *, void *, canl_principal *); + } canl_mech; struct canl_mech * diff --git a/emi.canl.canl-c/src/canl_ssl.c b/emi.canl.canl-c/src/canl_ssl.c index 219df98..f69b1aa 100644 --- a/emi.canl.canl-c/src/canl_ssl.c +++ b/emi.canl.canl-c/src/canl_ssl.c @@ -810,6 +810,44 @@ canl_ctx_set_ssl_cred(canl_ctx cc, char *cert, char *key, return err; } +static canl_err_code +ssl_get_peer(glb_ctx *cc, io_handler *io, void *auth_ctx, canl_principal *peer) +{ + struct _principal_int *princ; + SSL *ssl = (SSL *) auth_ctx; + X509 *cert = NULL; + X509_NAME *subject = NULL; + int ret; + + if (peer == NULL) + return set_error(cc, EINVAL, POSIX_ERROR, "invalid parameter value"); + + cert = SSL_get_peer_certificate(ssl); + if (cert == NULL) + return set_error(cc, CANL_ERR_NoClientCertificate, CANL_ERROR, "No peer certificate"); + + princ = calloc(1, sizeof(*princ)); + if (princ == NULL) + return set_error(cc, ENOMEM, POSIX_ERROR, "Not enough memory"); + + subject = X509_get_subject_name(cert); + princ->name = strdup(X509_NAME_oneline(subject, NULL, 0)); + if (princ->name == NULL) { + ret = set_error(cc, ENOMEM, POSIX_ERROR, "Not enough memory"); + goto end; + } + + *peer = princ; + princ = NULL; + ret = 0; + +end: + if (princ) + free(princ); + + return ret; +} + #ifdef DEBUG static void dbg_print_ssl_error(int errorcode) { @@ -861,5 +899,6 @@ struct canl_mech canl_mech_ssl = { ssl_accept, ssl_close, ssl_read, - ssl_write + ssl_write, + ssl_get_peer, }; -- 1.8.2.3