# HG changeset patch # User Will Fiveash # Date 1280357251 18000 # Node ID 2df46ea8f1b11b29be55f45b5e851fc74faac7d9 # Parent 982975ba6ebabab934ace0a77d174d77c27ff551 6929628 pkinit preauth plugin needs interface so caller can provide PIN diff -r 982975ba6eba -r 2df46ea8f1b1 exception_lists/copyright --- a/exception_lists/copyright Wed Jul 28 14:00:54 2010 -0700 +++ b/exception_lists/copyright Wed Jul 28 17:47:31 2010 -0500 @@ -304,14 +304,11 @@ usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.c usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.h -usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto.h -usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_lib.c usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_matching.c usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_profile.c usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_srv.c -usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h usr/src/lib/krb5/ss/copyright.h usr/src/lib/krb5/ss/mit-sipb-copyright.h usr/src/lib/krb5/ss/options.c diff -r 982975ba6eba -r 2df46ea8f1b1 usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h --- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h Wed Jul 28 14:00:54 2010 -0700 +++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h Wed Jul 28 17:47:31 2010 -0500 @@ -28,6 +28,10 @@ * SUCH DAMAGES. */ +/* + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + */ + #ifndef _PKINIT_H #define _PKINIT_H @@ -196,6 +200,7 @@ char *token_label; char *cert_id_string; char *cert_label; + char *PIN; /* Solaris Kerberos */ #endif } pkinit_identity_opts; diff -r 982975ba6eba -r 2df46ea8f1b1 usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c --- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c Wed Jul 28 14:00:54 2010 -0700 +++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c Wed Jul 28 17:47:31 2010 -0500 @@ -28,6 +28,10 @@ * SUCH DAMAGES. */ +/* + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + */ + #include #include #include @@ -1472,6 +1476,11 @@ pkiDebug("Setting flag to use RSA_PROTOCOL\n"); plgctx->opts->dh_or_rsa = RSA_PROTOCOL; } + } else if (strcmp(attr, "PIN") == 0) { + /* Solaris Kerberos: handle our PIN attr */ + plgctx->idopts->PIN = strdup(value); + if (plgctx->idopts->PIN == NULL) + return ENOMEM; } return 0; } diff -r 982975ba6eba -r 2df46ea8f1b1 usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c --- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c Wed Jul 28 14:00:54 2010 -0700 +++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c Wed Jul 28 17:47:31 2010 -0500 @@ -769,6 +769,7 @@ ctx->slotid = PK_NOSLOT; ctx->token_label = NULL; ctx->cert_label = NULL; + ctx->PIN = NULL; ctx->session = CK_INVALID_HANDLE; ctx->p11 = NULL; ctx->p11flags = 0; /* Solaris Kerberos */ @@ -811,6 +812,10 @@ free(ctx->cert_id); if (ctx->cert_label != NULL) free(ctx->cert_label); + if (ctx->PIN != NULL) { + (void) memset(ctx->PIN, 0, strlen(ctx->PIN)); + free(ctx->PIN); + } #endif } @@ -3363,6 +3368,10 @@ return CKR_OK; } +/* + * Solaris Kerberos: this function was changed to support a PIN being passed + * in. If that is the case the user will not be prompted for their PIN. + */ static krb5_error_code pkinit_login(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, @@ -3378,6 +3387,15 @@ if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) { rdat.data = NULL; rdat.length = 0; + } else if (id_cryptoctx->PIN != NULL) { + if ((rdat.data = strdup(id_cryptoctx->PIN)) == NULL) + return (ENOMEM); + /* + * Don't include NULL string terminator in length calculation as this + * PIN is passed to the C_Login function and only the text chars should + * be considered to be the PIN. + */ + rdat.length = strlen(id_cryptoctx->PIN); } else { unsigned char *lastnonwspc, *iterp; /* Solaris Kerberos - trim token label */ int count; @@ -3409,8 +3427,12 @@ (void) strlcat(prompt, gettext(" (Warning: PIN final try)"), prompt_len); else if (tip->flags & CKF_USER_PIN_COUNT_LOW) (void) strlcat(prompt, gettext(" (Warning: PIN count low)"), prompt_len); - rdat.data = (char *)malloc(tip->ulMaxPinLen + 2); + rdat.data = malloc(tip->ulMaxPinLen + 2); rdat.length = tip->ulMaxPinLen + 1; + /* + * Note that the prompter function will set rdat.length such that the + * NULL terminator is not included + */ kprompt.prompt = prompt; kprompt.hidden = 1; @@ -3421,7 +3443,7 @@ k5int_set_prompt_types(context, &prompt_type); r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data, NULL, NULL, 1, &kprompt); - k5int_set_prompt_types(context, 0); + k5int_set_prompt_types(context, NULL); free(prompt); } @@ -3441,8 +3463,10 @@ id_cryptoctx->p11flags |= C_LOGIN_DONE; } } - if (rdat.data) + if (rdat.data) { + (void) memset(rdat.data, 0, rdat.length); free(rdat.data); + } return r; } @@ -4105,27 +4129,33 @@ pkiDebug("Initial PKCS12_parse with no password failed\n"); - (void) memset(prompt_reply, '\0', sizeof(prompt_reply)); - rdat.data = prompt_reply; - rdat.length = sizeof(prompt_reply); - - r = snprintf(prompt_string, sizeof(prompt_string), "%s %s", - prompt_prefix, idopts->cert_filename); - if (r >= sizeof(prompt_string)) { - pkiDebug("Prompt string, '%s %s', is too long!\n", - prompt_prefix, idopts->cert_filename); - goto cleanup; + if (id_cryptoctx->PIN != NULL) { + /* Solaris Kerberos: use PIN if set */ + rdat.data = id_cryptoctx->PIN; + /* note rdat.length isn't needed in this case */ + } else { + (void) memset(prompt_reply, '\0', sizeof(prompt_reply)); + rdat.data = prompt_reply; + rdat.length = sizeof(prompt_reply); + + r = snprintf(prompt_string, sizeof(prompt_string), "%s %s", + prompt_prefix, idopts->cert_filename); + if (r >= sizeof(prompt_string)) { + pkiDebug("Prompt string, '%s %s', is too long!\n", + prompt_prefix, idopts->cert_filename); + goto cleanup; + } + kprompt.prompt = prompt_string; + kprompt.hidden = 1; + kprompt.reply = &rdat; + prompt_type = KRB5_PROMPT_TYPE_PREAUTH; + + /* PROMPTER_INVOCATION */ + k5int_set_prompt_types(context, &prompt_type); + r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data, + NULL, NULL, 1, &kprompt); + k5int_set_prompt_types(context, NULL); } - kprompt.prompt = prompt_string; - kprompt.hidden = 1; - kprompt.reply = &rdat; - prompt_type = KRB5_PROMPT_TYPE_PREAUTH; - - /* PROMPTER_INVOCATION */ - k5int_set_prompt_types(context, &prompt_type); - r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data, - NULL, NULL, 1, &kprompt); - k5int_set_prompt_types(context, 0); ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL); if (ret == 0) { @@ -4389,6 +4419,11 @@ if (id_cryptoctx->cert_label == NULL) return ENOMEM; } + if (idopts->PIN != NULL) { + id_cryptoctx->PIN = strdup(idopts->PIN); + if (id_cryptoctx->PIN == NULL) + return ENOMEM; + } /* Convert the ascii cert_id string into a binary blob */ /* * Solaris Kerberos: diff -r 982975ba6eba -r 2df46ea8f1b1 usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h --- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h Wed Jul 28 14:00:54 2010 -0700 +++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h Wed Jul 28 17:47:31 2010 -0500 @@ -80,6 +80,7 @@ CK_SLOT_ID slotid; char *token_label; char *cert_label; + char *PIN; /* Solaris Kerberos: */ /* These are crypto-specific */ void *p11_module; CK_SESSION_HANDLE session; diff -r 982975ba6eba -r 2df46ea8f1b1 usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c --- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c Wed Jul 28 14:00:54 2010 -0700 +++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c Wed Jul 28 17:47:31 2010 -0500 @@ -28,6 +28,10 @@ * SUCH DAMAGES. */ +/* + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + */ + #include #include #include @@ -136,6 +140,7 @@ opts->token_label = NULL; opts->cert_id_string = NULL; opts->cert_label = NULL; + opts->PIN = NULL; #endif *idopts = opts; @@ -219,6 +224,11 @@ if (newopts->cert_label == NULL) goto cleanup; } + if (src_opts->PIN != NULL) { + newopts->PIN = strdup(src_opts->PIN); + if (newopts->PIN == NULL) + goto cleanup; + } #endif @@ -255,6 +265,10 @@ free(idopts->cert_id_string); if (idopts->cert_label != NULL) free(idopts->cert_label); + if (idopts->PIN != NULL) { + (void) memset(idopts->PIN, 0, strlen(idopts->PIN)); + free(idopts->PIN); + } #endif free(idopts); } diff -r 982975ba6eba -r 2df46ea8f1b1 usr/src/lib/pam_modules/krb5/krb5_authenticate.c --- a/usr/src/lib/pam_modules/krb5/krb5_authenticate.c Wed Jul 28 14:00:54 2010 -0700 +++ b/usr/src/lib/pam_modules/krb5/krb5_authenticate.c Wed Jul 28 17:47:31 2010 -0500 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -499,7 +498,7 @@ KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME }; - krb5_get_init_creds_opt opts; + krb5_get_init_creds_opt *opts = NULL; krb5_kdc_rep *as_reply = NULL; /* * "result" should not be assigned PAM_SUCCESS unless @@ -515,8 +514,6 @@ "PAM-KRB5 (auth): attempt_krb5_auth: start: user='%s'", user ? user : ""); - krb5_get_init_creds_opt_init(&opts); - /* need to free context with krb5_free_context */ if (code = krb5_init_secure_context(&kmd->kcontext)) { __pam_log(LOG_AUTH | LOG_ERR, @@ -632,35 +629,44 @@ } else my_creds->times.renew_till = 0; - krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime); + code = krb5_get_init_creds_opt_alloc(kmd->kcontext, &opts); + if (code != 0) { + __pam_log(LOG_AUTH | LOG_ERR, + "Error allocating gic opts: %s", + error_message(code)); + result = PAM_SYSTEM_ERR; + goto out; + } + + krb5_get_init_creds_opt_set_tkt_life(opts, lifetime); if (proxiable_flag) { /* Set in config file */ if (kmd->debug) __pam_log(LOG_AUTH | LOG_DEBUG, "PAM-KRB5 (auth): Proxiable tickets " "requested"); - krb5_get_init_creds_opt_set_proxiable(&opts, TRUE); + krb5_get_init_creds_opt_set_proxiable(opts, TRUE); } if (forwardable_flag) { if (kmd->debug) __pam_log(LOG_AUTH | LOG_DEBUG, "PAM-KRB5 (auth): Forwardable tickets " "requested"); - krb5_get_init_creds_opt_set_forwardable(&opts, TRUE); + krb5_get_init_creds_opt_set_forwardable(opts, TRUE); } if (renewable_flag) { if (kmd->debug) __pam_log(LOG_AUTH | LOG_DEBUG, "PAM-KRB5 (auth): Renewable tickets " "requested"); - krb5_get_init_creds_opt_set_renew_life(&opts, rlife); + krb5_get_init_creds_opt_set_renew_life(opts, rlife); } if (no_address_flag) { if (kmd->debug) __pam_log(LOG_AUTH | LOG_DEBUG, "PAM-KRB5 (auth): Addressless tickets " "requested"); - krb5_get_init_creds_opt_set_address_list(&opts, NULL); + krb5_get_init_creds_opt_set_address_list(opts, NULL); } /* @@ -686,28 +692,30 @@ KRB5_PADATA_PK_AS_REQ, KRB5_PADATA_PK_AS_REQ_OLD }; - krb5_get_init_creds_opt_set_preauth_list(&opts, pk_pa_list, 2); + krb5_get_init_creds_opt_set_preauth_list(opts, pk_pa_list, 2); + + if (*krb5_pass == NULL || strlen(*krb5_pass) != 0) { + if (*krb5_pass != NULL) { + /* treat the krb5_pass as a PIN */ + code = krb5_get_init_creds_opt_set_pa( + kmd->kcontext, opts, "PIN", *krb5_pass); + } - if (*krb5_pass == NULL) { - /* let preauth plugin prompt for PIN */ - code = __krb5_get_init_creds_password(kmd->kcontext, - my_creds, - me, - NULL, /* clear text passwd */ - pam_krb5_prompter, /* prompter */ - pamh, /* prompter data */ - 0, /* start time */ - NULL, /* defaults to krbtgt@REALM */ - &opts, - &as_reply); + if (!code) { + code = __krb5_get_init_creds_password( + kmd->kcontext, + my_creds, + me, + NULL, /* clear text passwd */ + pam_krb5_prompter, /* prompter */ + pamh, /* prompter data */ + 0, /* start time */ + NULL, /* defaults to krbtgt@REALM */ + opts, + &as_reply); + } } else { - /* - * krb pkinit does not support setting the PIN so we - * punt on trying to use krb5_pass as the PIN for now. - * Note that once this is supported by pkinit the code - * should make sure krb5_pass isn't empty and if it is - * then that's an error. - */ + /* invalid PIN */ code = KRB5KRB_AP_ERR_BAD_INTEGRITY; } } else { @@ -725,7 +733,7 @@ KRB5_PADATA_ENC_TIMESTAMP }; - krb5_get_init_creds_opt_set_preauth_list(&opts, + krb5_get_init_creds_opt_set_preauth_list(opts, pk_pa_list, 1); /* @@ -743,7 +751,7 @@ NULL, /* data */ 0, /* start time */ NULL, /* defaults to krbtgt@REALM */ - &opts, + opts, &as_reply); } } @@ -951,6 +959,8 @@ krb5_free_context(kmd->kcontext); kmd->kcontext = NULL; } + if (opts) + krb5_get_init_creds_opt_free(kmd->kcontext, opts); if (kmd->debug) __pam_log(LOG_AUTH | LOG_DEBUG,