On Thu, Aug 28, 2008 at 08:22:27PM +0200, Mark Phalan wrote: > > > I've just uploaded a webrev of my resync/pkinit workspace. There still > needs to be some work on pkinit so don't expect the code in > usr/src/lib/krb5/plugins/preauth/pkinit/ to be complete (you can ignore > it for now). I'll post another incremental webrev with any changes I > make to the pkinit code later on. The rest of the changes are resync > changes for MIT 1.6.3. The hg comment needs to be updated, I'll do that > once we get the pkinit PSARC case submitted. > > I've chunked the review up into four pieces as I expect the krb team to > do the review. > > Shawn: Chunk 1 > Peter: Chunk 2 > Glenn: Chunk 3 > Will: Chunk 4 > > I'd like to have this completed by 17th Sept. Let me know if thats a > problem for anyone. > > webrev here: > http://cr.opensolaris.org/~mbp/pkinit/
Have you run this code through the lint -errsecurity=standard security checks? <see http://secprog.sfbay.sun.com/lint/levels.html> Have you compiled with DEBUG defined to make sure the plugin still works? ======================================================================================= Chunk 4 code review: In usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c static int pkinit_oids_refs = 0; and pkinit_init_pkinit_oids(): pkinit_oids_refs++; and pkinit_fini_pkinit_oids(): /* Only call OBJ_cleanup once! */ if (--pkinit_oids_refs == 0) OBJ_cleanup(); - Any thread safety issues here? pkinit_init_req_crypto(): *cryptoctx = ctx; - Other funcs would test an output arg like cryptoctx for NULL and return EINVAL. This should too I guess. out: if (retval) free(ctx); - In earlier funcs ctx was tested for NULL as a condition prior to calling free(). To be safe, that should happen here as well. static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx) { krb5_error_code retval = ENOMEM; int i; for (i = 0; i < MAX_CREDS_ALLOWED; i++) ctx->creds[i] = NULL; ctx->my_certs = NULL; ctx->cert_index = 0; ctx->my_key = NULL; ctx->trustedCAs = NULL; ctx->intermediateCAs = NULL; ctx->revoked = NULL; retval = 0; return retval; } - The retval assignments are unnecessary (just return 0). cms_signeddata_create(): /* start creating PKCS7 data */ if ((p7 = PKCS7_new()) == NULL) - Are allocation functions like PKCS7_new() allocating zero'ed out structs? If not, do you think they should? *signed_data_len = i2d_PKCS7(p7, NULL); - Again, an instance of an output var. assignment without testing for NULL. This should be handled consistently one way or another. /* fill-in PKCS7_SIGNER_INFO */ if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL) goto cleanup; if (!ASN1_INTEGER_set(p7si->version, 1)) goto cleanup; if (!X509_NAME_set(&p7si->issuer_and_serial->issuer, X509_get_issuer_name(cert))) goto cleanup; - Opportunity for mem leaks in regards to the error path and p7si? cms_envelopeddata_create(): switch (pa_type) { case KRB5_PADATA_PK_AS_REQ: p7->d.enveloped->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_signed); break; case KRB5_PADATA_PK_AS_REP_OLD: case KRB5_PADATA_PK_AS_REQ_OLD: p7->d.enveloped->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_data); break; break; break; break; } - too breaky. pkinit_create_td_dh_parameters(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, pkinit_req_crypto_context req_cryptoctx, pkinit_identity_crypto_context id_cryptoctx, pkinit_plg_opts *opts, krb5_data **out_data) { krb5_error_code retval = ENOMEM; unsigned int buf1_len = 0, buf2_len = 0, buf3_len = 0, i = 0; unsigned char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL; krb5_typed_data **typed_data = NULL; krb5_data *data = NULL, *encoded_algId = NULL; krb5_algorithm_identifier **algId = NULL; if (opts->dh_min_bits > 4096) goto cleanup; - retval looks wrong in regards to the first goto there. In fact there are several functions in this file that have this problem. crypto_check_cert_eku(): *valid_eku = 0; if (reqctx->received_cert == NULL) goto cleanup; - I don't think "*valid_eku = 0" should occur before the input is checked. The caller must check the return of crypto_check_cert_eku() before checking *valid_eku value. pkinit_octetstring2key(): key_block->magic = 0; - Why not KV5M_KEYBLOCK? client_create_dh(): krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; unsigned char *buf = NULL; int dh_err = 0; ASN1_INTEGER *pub_key = NULL; if (cryptoctx->dh == NULL) { if ((cryptoctx->dh = DH_new()) == NULL) goto cleanup; - Again retval doesn't seem right for first goto cleanup error path. DH_check(cryptoctx->dh, &dh_err); if (dh_err != 0) { pkiDebug("Warning: dh_check failed with %d\n", dh_err); if (dh_err & DH_CHECK_P_NOT_PRIME) pkiDebug("p value is not prime\n"); if (dh_err & DH_CHECK_P_NOT_SAFE_PRIME) pkiDebug("p value is not a safe prime\n"); if (dh_err & DH_UNABLE_TO_CHECK_GENERATOR) pkiDebug("unable to check the generator value\n"); if (dh_err & DH_NOT_SUITABLE_GENERATOR) pkiDebug("the g value is not a generator\n"); } - Why don't the errors above cause the function to goto cleanup? If they are meaningless then why call DH_check()? client_process_dh(): if (der_decode_data(subjectPublicKey_data, (long)subjectPublicKey_length, &data, &data_len) != 0) { pkiDebug("failed to decode subjectPublicKey\n"); retval = -1; goto cleanup; } - Will a retval = -1 be interpreted/mapped correctly? if ((pub_key = d2i_ASN1_INTEGER(NULL, &p, data_len)) == NULL) goto cleanup; if ((server_pub_key = ASN1_INTEGER_to_BN(pub_key, NULL)) == NULL) goto cleanup; - These don't look like KRB5KDC_ERR_PREAUTH_FAILED errors to me. server_process_dh(): if (!DH_generate_key(dh_server)) goto cleanup; - Seems like the real error may be lost here. i2d_ASN1_INTEGER(pub_key, &p); - should have (void) cast. This occurs in other places as well. pkinit_open_session(): /* Init */ /* Solaris Kerberos XXX */ r = cctx->p11->C_Initialize(NULL); and if ((r = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION, NULL, NULL, &cctx->session)) != CKR_OK) - Be aware that pkcs11 session handles are not fork safe. Do you know whether the cctx will be used across a fork? See: 5102151 krb contexts are not fork safe for the krb bug relating to this issue. ============================================================================ Stopping here for the day. -- Will Fiveash Sun Microsystems Inc. http://opensolaris.org/os/project/kerberos/