diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2002-05-31 01:40:37 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2002-05-31 01:40:37 +0000 |
commit | e422cf5418cad6a2707d49a7d1938dd4e613244d (patch) | |
tree | 78beeb0388a8991f2f37052c067715221ed028ac | |
parent | 996641282f6f85a317c92c3228939eaf1af25f1d (diff) |
Add support for passphrase authentication, all sorts of new attributes
to check for. Verified that it works well with mod_dav (not in the tree).
-rw-r--r-- | usr.sbin/httpd/src/modules/keynote/mod_keynote.c | 201 |
1 files changed, 153 insertions, 48 deletions
diff --git a/usr.sbin/httpd/src/modules/keynote/mod_keynote.c b/usr.sbin/httpd/src/modules/keynote/mod_keynote.c index 0264a081971..741904c608a 100644 --- a/usr.sbin/httpd/src/modules/keynote/mod_keynote.c +++ b/usr.sbin/httpd/src/modules/keynote/mod_keynote.c @@ -31,6 +31,7 @@ */ #include <mod_ssl.h> +#include <ap_sha1.h> #include <keynote.h> MODULE_VAR_EXPORT module keynote_module; @@ -84,7 +85,6 @@ merge_keynote_dir_config(pool *p, void *basev, void *addv) static void add_action_attribute(int sessid, char *name, char *value, request_rec *r) { - if (kn_add_action(sessid, name, value, 0) == 0) return; @@ -122,17 +122,58 @@ add_action_attribute(int sessid, char *name, char *value, request_rec *r) * app_domain -> apache * method -> GET, HEAD, POST, etc. * uri -> the URI that got us here + * protocol -> access protocol + * GMTTimeOfDay -> GMT time of day, in YYYYmmddHHMMSS format + * LocalTimeOfDay -> Local time of day, in YYYYmmddHHMMSS format + * filename -> last component of URI, or "" if not found + * local address + * remote address + * remote hostname, if known/resolved + * local hostname + * remote username (RFC 1413) + * local username (if authentication was done) + * authentication type -> Basic, Digest, etc. + * + * SSL information is set at check_keynote_assertions() * - * XXX should probably add more stuff... - * cert expiration date? - * current time? + * XXX IPsec information (if any) */ static void add_action_attributes(int sessid, request_rec *r) { + time_t tt; + char mytimeofday[15]; add_action_attribute(sessid, "app_domain", "apache", r); add_action_attribute(sessid, "method", (char *)r->method, r); + add_action_attribute(sessid, "protocol", r->protocol, r); + add_action_attribute(sessid, "filename", r->filename, r); + + tt = time((time_t) NULL); + strftime (mytimeofday, 14, "%Y%m%d%H%M%S", gmtime (&tt)); + add_action_attribute(sessid, "GMTTimeOfDay", mytimeofday, r); + + strftime (mytimeofday, 14, "%Y%m%d%H%M%S", localtime (&tt)); + add_action_attribute(sessid, "LocalTimeOfDay", mytimeofday, r); + + add_action_attribute(sessid, "local_address", r->connection->local_ip, r); + add_action_attribute(sessid, "remote_adress", r->connection->remote_ip, r); + + if (r->connection->local_host != NULL) + add_action_attribute(sessid, "local_hostname", + r->connection->local_host, r); + + if (r->connection->remote_host != NULL) + add_action_attribute(sessid, "remote_hostname", + r->connection->remote_host, r); + + if (r->connection->user != NULL) + add_action_attribute(sessid, "local_username", r->connection->user, r); + + if (r->connection->remote_logname != NULL) + add_action_attribute(sessid, "remote_username", + r->connection->remote_logname, r); + /* XXX - make the split URI components available too? */ add_action_attribute(sessid, "uri", r->unparsed_uri, r); } @@ -556,7 +597,7 @@ static int check_keynote_assertions(request_rec *r) { array_header *policy_asserts = (array_header *)ap_get_module_config(r->per_dir_config, &keynote_module); - int sessid, res, i; + int sessid, res, i, noclientcert = 0; int rval = OK; char **assertions; SSL_CTX *ctx; @@ -566,53 +607,110 @@ check_keynote_assertions(request_rec *r) STACK_OF(X509_NAME) *CA_list; X509_NAME *issuer, *subject; static char *return_values[] = { "false", "true" }; + AP_SHA1_CTX context; + unsigned char digest[SHA_DIGESTSIZE]; + char *pwauth; + const char *sent_pw; /* If there are no KeyNote assertions we have nothing to do. */ if (policy_asserts->nelts == 0) return(DECLINED); - /* If this is not an SSL'd connection we deny them. */ - if ((ssl = ap_ctx_get(r->connection->client->ctx, "ssl")) == NULL) - return(FORBIDDEN); - ctx = SSL_get_SSL_CTX(ssl); + /* Initialize keynote session. */ + sessid = kn_init(); - /* Get client's certificate or deny them */ - certstack = SSL_get_peer_cert_chain(ssl); - if ((cert = SSL_get_peer_certificate(ssl)) == NULL) - return(FORBIDDEN); + /* If this is an SSL session, see if client certs were used. */ + if ((ssl = ap_ctx_get(r->connection->client->ctx, "ssl")) != NULL) { + ctx = SSL_get_SSL_CTX(ssl); - /* Missing or self-signed, deny them */ - issuer = X509_get_issuer_name(cert); - subject = X509_get_subject_name(cert); - if (!issuer || !subject || X509_name_cmp(issuer, subject) == NULL) - return(FORBIDDEN); + /* XXX Initialize SSL-related action attributes */ - /* Initialize keynote and setup our environment */ - sessid = kn_init(); - add_action_attributes(sessid, r); + /* Get client's certificate or deny them */ + certstack = SSL_get_peer_cert_chain(ssl); + if ((cert = SSL_get_peer_certificate(ssl)) != NULL) { + /* Missing or self-signed, deny them */ + issuer = X509_get_issuer_name(cert); + subject = X509_get_subject_name(cert); + if (!issuer || !subject || X509_name_cmp(issuer, subject) == NULL) + return(FORBIDDEN); - /* Build a set of fake assertions corresponding to the certificate chain. */ - for (i = 0; i < sk_X509_num(certstack) && (icert = sk_X509_value(certstack, i)); i++) { - if (keynote_fake_assertion(r, sessid, cert, X509_get_pubkey(icert), X509_get_subject_name(icert)) == -1) - return(FORBIDDEN); - cert = icert; - } + /* Build a set of fake assertions corresponding to the certificate chain. */ + for (i = 0; i < sk_X509_num(certstack) && (icert = sk_X509_value(certstack, i)); i++) { + if (keynote_fake_assertion(r, sessid, cert, X509_get_pubkey(icert), X509_get_subject_name(icert)) == -1) + return(FORBIDDEN); + cert = icert; + } - /* The issuer of the last cert in the chain should be in the CA list. */ - issuer = X509_get_issuer_name(cert); - CA_list = SSL_CTX_get_client_CA_list(ctx); - for (i = 0; i < sk_X509_num(CA_list); i++) { - subject = sk_X509_NAME_value(CA_list, i); - if (subject && X509_NAME_cmp(issuer, subject) == 0) { - /* An X509_NAME does not contain the public key */ - if (keynote_fake_assertion(r, sessid, cert, NULL, subject) == -1) + /* The issuer of the last cert in the chain should be in the CA list. */ + issuer = X509_get_issuer_name(cert); + CA_list = SSL_CTX_get_client_CA_list(ctx); + for (i = 0; i < sk_X509_num(CA_list); i++) { + subject = sk_X509_NAME_value(CA_list, i); + if (subject && X509_NAME_cmp(issuer, subject) == 0) { + /* An X509_NAME does not contain the public key. */ + if (keynote_fake_assertion(r, sessid, cert, NULL, subject) == -1) + return(FORBIDDEN); + break; + } + } + + if (i >= sk_X509_num(CA_list)) + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r->connection->server, + "didn't find CA for issuer of last cert in chain"); + + /* Add the user's public key as an authorizer. */ + if (keynote_add_authorizer(r, sessid, cert) == -1) return(FORBIDDEN); - break; + } else + noclientcert = 1; /* No client certificates used. */ + } else + noclientcert = 1; /* SSL was not used. */ + + /* See if we have a passphrase. */ + if (noclientcert == 1) { + if ((res = ap_get_basic_auth_pw(r, &sent_pw)) == 0) { + /* Add passphrase as the authorizer. */ + ap_SHA1Init(&context); + ap_SHA1Update(&context, sent_pw, strlen(sent_pw)); + ap_SHA1Final(digest, &context); + + pwauth = calloc(120, sizeof(char)); + if (pwauth == NULL) { + kn_close(sessid); + return(FORBIDDEN); + } + res = strlen("passphrase-sha1-base64:"); + strlcpy(pwauth, "passphrase-sha1-base64:", res + 1); + ap_base64encode_binary(pwauth + strlen(pwauth), digest, + sizeof(digest)); + + /* Add passphrase authorizer directly to the session. */ + kn_add_authorizer(sessid, pwauth); + free(pwauth); + + /* Add username as a principal too. */ + if (r->connection->user != NULL) { + pwauth = calloc(strlen(r->connection->user) + 1 + + strlen("username:"), sizeof(char)); + if (pwauth == NULL) { + kn_close(sessid); + return(FORBIDDEN); + } + + snprintf(pwauth, strlen(r->connection->user) + 1 + + strlen("username:"), "username:%s", + r->connection->user); + + kn_add_authorizer(sessid, pwauth); + free(pwauth); + } + } else { + kn_add_authorizer(sessid, ""); } } - if (i >= sk_X509_num(CA_list)) - ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r->connection->server, - "didn't find CA for issuer of last cert in chain"); + + /* Setup our environment. */ + add_action_attributes(sessid, r); /* Add our policy assertions (as specified in the config file). */ assertions = (char **)policy_asserts->elts; @@ -644,10 +742,6 @@ check_keynote_assertions(request_rec *r) } } - /* Add the user's public key as an authorizer. */ - if (keynote_add_authorizer(r, sessid, cert) == -1) - return(FORBIDDEN); - /* Now do the actual query. */ switch ((res = kn_do_query(sessid, return_values, 2))) { case 0: @@ -714,10 +808,10 @@ done: static const char * store_assertion(cmd_parms *cmd, void *policy_assertsv, char *filename) { - int fd, serrno; + int fd, serrno, nelts = 0; ssize_t nread; struct stat sb; - char *assert; + char *assert, **asrts; array_header *policy_asserts = (array_header *)policy_assertsv; filename = ap_server_root_relative(cmd->pool, filename); @@ -729,7 +823,7 @@ store_assertion(cmd_parms *cmd, void *policy_assertsv, char *filename) return(ap_pstrcat(cmd->pool, "Can't fstat ", filename, ": ", strerror(errno), NULL)); - assert = ap_pcalloc(cmd->pool, sb.st_size + 1); + assert = calloc(sb.st_size + 1, sizeof(char)); nread = read(fd, assert, sb.st_size); serrno = errno; close(fd); @@ -741,8 +835,19 @@ store_assertion(cmd_parms *cmd, void *policy_assertsv, char *filename) return(ap_pstrcat(cmd->pool, "Short read from", filename, NULL)); } - /* Now store the assertion in the array */ - *(char **)ap_push_array(policy_asserts) = assert; + /* Break up into constituent assertions */ + asrts = kn_read_asserts(assert, sb.st_size, &nelts); + free(assert); + + while (--nelts >= 0) { + /* Now store the individual assertions in the array */ + *(char **)ap_push_array(policy_asserts) = ap_pstrdup(cmd->pool, asrts[nelts]); + free(asrts[nelts]); + } + + /* We don't need this anymore */ + if (asrts) + free(asrts); return(NULL); } |