Remove support for the old pa-sam-challenge and pa-sam-response
authorSam Hartman <hartmans@mit.edu>
Fri, 1 Oct 2010 17:12:26 +0000 (17:12 +0000)
committerSam Hartman <hartmans@mit.edu>
Fri, 1 Oct 2010 17:12:26 +0000 (17:12 +0000)
preauth type per discussion on krbdev.  The pa-sam-challenge-2 code
remains in the client.

preauth: remove pa-sam-challenge

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24403 dc483132-0cff-0310-8789-dd5450dbe970

src/kdc/kdc_preauth.c
src/lib/krb5/krb/preauth2.c

index 503c2313b82aa53f2b9da6c48b2e5a16465b198e..0c477266b35c937155aeb5e15b8304b9127771bb 100644 (file)
@@ -202,35 +202,6 @@ return_pw_salt(krb5_context, krb5_pa_data * padata,
                void *pa_system_context,
                void **pa_request_context);
 
-/* SAM preauth support */
-static krb5_error_code
-verify_sam_response(krb5_context, krb5_db_entry *client,
-                    krb5_data *req_pkt,
-                    krb5_kdc_req *request,
-                    krb5_enc_tkt_part * enc_tkt_reply, krb5_pa_data *data,
-                    preauth_get_entry_data_proc get_entry_data,
-                    void *pa_module_context,
-                    void **pa_request_context,
-                    krb5_data **e_data,
-                    krb5_authdata ***authz_data);
-
-static krb5_error_code
-get_sam_edata(krb5_context, krb5_kdc_req *request,
-              krb5_db_entry *client, krb5_db_entry *server,
-              preauth_get_entry_data_proc get_entry_data,
-              void *pa_module_context,
-              krb5_pa_data *data);
-static krb5_error_code
-return_sam_data(krb5_context, krb5_pa_data * padata,
-                krb5_db_entry *client,
-                krb5_data *req_pkt,
-                krb5_kdc_req *request, krb5_kdc_rep *reply,
-                krb5_key_data *client_key,
-                krb5_keyblock *encrypting_key,
-                krb5_pa_data **send_pa,
-                preauth_get_entry_data_proc get_entry_data,
-                void *pa_module_context,
-                void **pa_request_context);
 
 #if APPLE_PKINIT
 /* PKINIT preauth support */
@@ -339,28 +310,6 @@ static krb5_preauth_systems static_preauth_systems[] = {
         0,
         return_pw_salt
     },
-    {
-        "sam-response",
-        KRB5_PADATA_SAM_RESPONSE,
-        0,
-        NULL,
-        NULL,
-        NULL,
-        0,
-        verify_sam_response,
-        return_sam_data
-    },
-    {
-        "sam-challenge",
-        KRB5_PADATA_SAM_CHALLENGE,
-        PA_HARDWARE,            /* causes get_preauth_hint_list to use this */
-        NULL,
-        NULL,
-        NULL,
-        get_sam_edata,
-        0,
-        0
-    },
     {
         "pac-request",
         KRB5_PADATA_PAC_REQUEST,
@@ -1868,681 +1817,7 @@ cleanup:
     return retval;
 }
 
-static krb5_error_code
-return_sam_data(krb5_context context, krb5_pa_data *in_padata,
-                krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request,
-                krb5_kdc_rep *reply, krb5_key_data *client_key,
-                krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
-                preauth_get_entry_data_proc sam_get_entry_data,
-                void *pa_system_context,
-                void **pa_request_context)
-{
-    krb5_error_code     retval;
-    krb5_data           scratch;
-    int                 i;
-
-    krb5_sam_response           *sr = 0;
-    krb5_predicted_sam_response *psr = 0;
-
-    if (in_padata->contents == 0)
-        return 0;
-
-    /*
-     * We start by doing the same thing verify_sam_response() does:
-     * extract the psr from the padata (which is an sr). Nothing
-     * here should generate errors! We've already successfully done
-     * all this once.
-     */
-
-    scratch.data = (char *)in_padata->contents;
-    scratch.length = in_padata->length;
-
-    if ((retval = decode_krb5_sam_response(&scratch, &sr))) {
-        kdc_err(context, retval,
-                "return_sam_data(): decode_krb5_sam_response failed");
-        goto cleanup;
-    }
-
-    {
-        krb5_enc_data tmpdata;
-
-        tmpdata.enctype = ENCTYPE_UNKNOWN;
-        tmpdata.ciphertext = sr->sam_track_id;
-
-        scratch.length = tmpdata.ciphertext.length;
-        if ((scratch.data = (char *) malloc(scratch.length)) == NULL) {
-            retval = ENOMEM;
-            goto cleanup;
-        }
-
-        if ((retval = krb5_c_decrypt(context, &psr_key, /* XXX */ 0, 0,
-                                     &tmpdata, &scratch))) {
-            kdc_err(context, retval,
-                    "return_sam_data(): decrypt track_id failed");
-            free(scratch.data);
-            goto cleanup;
-        }
-    }
-
-    if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) {
-        kdc_err(context, retval,
-                "return_sam_data(): decode_krb5_predicted_sam_response failed");
-        free(scratch.data);
-        goto cleanup;
-    }
-
-    /* We could use sr->sam_flags, but it may be absent or altered. */
-    if (psr->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) {
-        kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED,
-                "Unsupported SAM flag must-pk-encrypt-sad");
-        goto cleanup;
-    }
-    if (psr->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) {
-        /* No key munging */
-        goto cleanup;
-    }
-    if (psr->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) {
-        /* Use sam_key instead of client key */
-        krb5_free_keyblock_contents(context, encrypting_key);
-        krb5_copy_keyblock_contents(context, &psr->sam_key, encrypting_key);
-        /* XXX Attach a useful pa_data */
-        goto cleanup;
-    }
-
-    /* Otherwise (no flags set), we XOR the keys */
-    /* XXX The passwords-04 draft is underspecified here wrt different
-       key types. We will do what I hope to get into the -05 draft. */
-    {
-        krb5_octet *p = encrypting_key->contents;
-        krb5_octet *q = psr->sam_key.contents;
-        int length = ((encrypting_key->length < psr->sam_key.length)
-                      ? encrypting_key->length
-                      : psr->sam_key.length);
-
-        for (i = 0; i < length; i++)
-            p[i] ^= q[i];
-    }
-
-    /* Post-mixing key correction */
-    switch (encrypting_key->enctype) {
-    case ENCTYPE_DES_CBC_CRC:
-    case ENCTYPE_DES_CBC_MD4:
-    case ENCTYPE_DES_CBC_MD5:
-    case ENCTYPE_DES_CBC_RAW:
-        mit_des_fixup_key_parity(encrypting_key->contents);
-        if (mit_des_is_weak_key(encrypting_key->contents))
-            ((krb5_octet *) encrypting_key->contents)[7] ^= 0xf0;
-        break;
-
-        /* XXX case ENCTYPE_DES3_CBC_MD5: listed in 1510bis-04 draft */
-    case ENCTYPE_DES3_CBC_SHA: /* XXX deprecated? */
-    case ENCTYPE_DES3_CBC_RAW:
-    case ENCTYPE_DES3_CBC_SHA1:
-        for (i = 0; i < 3; i++) {
-            mit_des_fixup_key_parity(encrypting_key->contents + i * 8);
-            if (mit_des_is_weak_key(encrypting_key->contents + i * 8))
-                ((krb5_octet *) encrypting_key->contents)[7 + i * 8] ^= 0xf0;
-        }
-        break;
-
-    default:
-        kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED,
-                "Unimplemented keytype for SAM key mixing");
-        goto cleanup;
-    }
-
-    /* XXX Attach a useful pa_data */
-cleanup:
-    if (sr)
-        krb5_free_sam_response(context, sr);
-    if (psr)
-        krb5_free_predicted_sam_response(context, psr);
-
-    return retval;
-}
-
-static struct {
-    char* name;
-    int   sam_type;
-} *sam_ptr, sam_inst_map[] = {
-    { "SNK4", PA_SAM_TYPE_DIGI_PATH, },
-    { "SECURID", PA_SAM_TYPE_SECURID, },
-    { "GRAIL", PA_SAM_TYPE_GRAIL, },
-    { 0, 0 },
-};
-
-static krb5_error_code
-get_sam_edata(krb5_context context, krb5_kdc_req *request,
-              krb5_db_entry *client, krb5_db_entry *server,
-              preauth_get_entry_data_proc sam_get_entry_data,
-              void *pa_system_context, krb5_pa_data *pa_data)
-{
-    krb5_error_code             retval;
-    krb5_sam_challenge          sc;
-    krb5_predicted_sam_response psr;
-    krb5_data *                 scratch;
-    krb5_keyblock encrypting_key, *mkey_ptr;
-    char response[9];
-    char inputblock[8];
-    krb5_data predict_response;
-
-    memset(&sc, 0, sizeof(sc));
-    memset(&psr, 0, sizeof(psr));
-
-    /*
-     *  Given the client name we can figure out what type of preauth
-     *  they need. The spec is currently for querying the database for
-     *  names that match the types of preauth used. Later we should
-     *  make this mapping show up in kdc.conf. In the meantime, we
-     *  hardcode the following:
-     *  /SNK4 -- Digital Pathways SNK/4 preauth.
-     *  /GRAIL -- experimental preauth
-     *  The first one found is used. See sam_inst_map above.
-     *
-     *  For SNK4 in particular, the key in the database is the key for
-     *  the device; kadmin needs a special interface for it.
-     */
-
-    {
-        krb5_db_entry *assoc;
-        krb5_key_data  *assoc_key;
-        krb5_principal newp;
-        int probeslot;
-
-        sc.sam_type = 0;
-
-        retval = krb5_copy_principal(kdc_context, request->client, &newp);
-        if (retval) {
-            kdc_err(kdc_context, retval, "copying client name for preauth probe");
-            return retval;
-        }
-
-        probeslot = krb5_princ_size(context, newp)++;
-        krb5_princ_name(kdc_context, newp) =
-            realloc(krb5_princ_name(kdc_context, newp),
-                    krb5_princ_size(context, newp) * sizeof(krb5_data));
-
-        for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) {
-            krb5_princ_component(kdc_context,newp,probeslot)->data = sam_ptr->name;
-            krb5_princ_component(kdc_context,newp,probeslot)->length =
-                strlen(sam_ptr->name);
-            retval = krb5_db_get_principal(kdc_context, newp, 0, &assoc);
-            if(retval == 0) {
-                sc.sam_type = sam_ptr->sam_type;
-                break;
-            }
-        }
-
-        krb5_princ_component(kdc_context,newp,probeslot)->data = 0;
-        krb5_princ_component(kdc_context,newp,probeslot)->length = 0;
-        krb5_princ_size(context, newp)--;
-
-        krb5_free_principal(kdc_context, newp);
-
-        /* if sc.sam_type is set, it worked */
-        if (sc.sam_type) {
-            /* so use assoc to get the key out! */
-            {
-                if ((retval = krb5_dbe_find_mkey(context, master_keylist,
-                                                 assoc, &mkey_ptr))) {
-                    krb5_keylist_node *tmp_mkey_list;
-                    /* try refreshing the mkey list in case it's been updated */
-                    if (krb5_db_fetch_mkey_list(context, master_princ,
-                                                &master_keyblock, 0,
-                                                &tmp_mkey_list) == 0) {
-                        krb5_dbe_free_key_list(context, master_keylist);
-                        master_keylist = tmp_mkey_list;
-                        if ((retval = krb5_dbe_find_mkey(context, master_keylist,
-                                                         assoc, &mkey_ptr))) {
-                            return (retval);
-                        }
-                    } else {
-                        return (retval);
-                    }
-                }
-
-                /* here's what do_tgs_req does */
-                retval = krb5_dbe_find_enctype(kdc_context, assoc,
-                                               ENCTYPE_DES_CBC_RAW,
-                                               KRB5_KDB_SALTTYPE_NORMAL,
-                                               0,    /* Get highest kvno */
-                                               &assoc_key);
-                if (retval) {
-                    char *sname;
-                    krb5_unparse_name(kdc_context, request->client, &sname);
-                    kdc_err(kdc_context, retval,
-                            "snk4 finding the enctype and key <%s>", sname);
-                    free(sname);
-                    return retval;
-                }
-                /* convert server.key into a real key */
-                retval = krb5_dbe_decrypt_key_data(kdc_context, mkey_ptr,
-                                                   assoc_key, &encrypting_key,
-                                                   NULL);
-                if (retval) {
-                    kdc_err(kdc_context, retval,
-                            "snk4 pulling out key entry");
-                    return retval;
-                }
-                /* now we can use encrypting_key... */
-            }
-        } else {
-            /* SAM is not an option - so don't return as hint */
-            return KRB5_PREAUTH_BAD_TYPE;
-        }
-    }
-    sc.magic = KV5M_SAM_CHALLENGE;
-    psr.sam_flags = sc.sam_flags = KRB5_SAM_USE_SAD_AS_KEY;
-
-    /* Replay prevention */
-    if ((retval = krb5_copy_principal(context, request->client, &psr.client)))
-        return retval;
-#ifdef USE_RCACHE
-    if ((retval = krb5_us_timeofday(context, &psr.stime, &psr.susec)))
-        return retval;
-#endif /* USE_RCACHE */
-
-    switch (sc.sam_type) {
-    case PA_SAM_TYPE_GRAIL:
-        sc.sam_type_name.data = "Experimental System";
-        sc.sam_type_name.length = strlen(sc.sam_type_name.data);
-        sc.sam_challenge_label.data = "experimental challenge label";
-        sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
-        sc.sam_challenge.data = "12345";
-        sc.sam_challenge.length = strlen(sc.sam_challenge.data);
-
-#if 0 /* Enable this to test "normal" (no flags set) mode.  */
-        psr.sam_flags = sc.sam_flags = 0;
-#endif
-
-        psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
-        /* string2key on sc.sam_challenge goes in here */
-        /* eblock is just to set the enctype */
-        {
-            const krb5_enctype type = ENCTYPE_DES_CBC_MD5;
-
-            if ((retval = krb5_c_string_to_key(context, type, &sc.sam_challenge,
-                                               0 /* salt */, &psr.sam_key)))
-                goto cleanup;
-
-            if ((retval = encode_krb5_predicted_sam_response(&psr, &scratch)))
-                goto cleanup;
-
-            {
-                size_t enclen;
-                krb5_enc_data tmpdata;
-
-                if ((retval = krb5_c_encrypt_length(context,
-                                                    psr_key.enctype,
-                                                    scratch->length, &enclen)))
-                    goto cleanup;
-
-                if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) {
-                    retval = ENOMEM;
-                    goto cleanup;
-                }
-                tmpdata.ciphertext.length = enclen;
-
-                if ((retval = krb5_c_encrypt(context, &psr_key,
-                                             /* XXX */ 0, 0, scratch, &tmpdata)))
-                    goto cleanup;
-
-                sc.sam_track_id = tmpdata.ciphertext;
-            }
-        }
-
-        sc.sam_response_prompt.data = "response prompt";
-        sc.sam_response_prompt.length = strlen(sc.sam_response_prompt.data);
-        sc.sam_pk_for_sad.length = 0;
-        sc.sam_nonce = 0;
-        /* Generate checksum */
-        /*krb5_checksum_size(context, ctype)*/
-        /*krb5_calculate_checksum(context,ctype,in,in_length,seed,
-          seed_length,outcksum) */
-        /*krb5_verify_checksum(context,ctype,cksum,in,in_length,seed,
-          seed_length) */
-#if 0 /* XXX a) glue appears broken; b) this gives up the SAD */
-        sc.sam_cksum.contents = (krb5_octet *)
-            malloc(krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES));
-        if (sc.sam_cksum.contents == NULL) return(ENOMEM);
-
-        retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES,
-                                         sc.sam_challenge.data,
-                                         sc.sam_challenge.length,
-                                         psr.sam_key.contents, /* key */
-                                         psr.sam_key.length, /* key length */
-                                         &sc.sam_cksum);
-        if (retval) { free(sc.sam_cksum.contents); return(retval); }
-#endif /* 0 */
-
-        retval = encode_krb5_sam_challenge(&sc, &scratch);
-        if (retval) goto cleanup;
-        pa_data->magic = KV5M_PA_DATA;
-        pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE;
-        pa_data->contents = (krb5_octet *)scratch->data;
-        pa_data->length = scratch->length;
-
-        retval = 0;
-        break;
-    case PA_SAM_TYPE_DIGI_PATH:
-        sc.sam_type_name.data = "Digital Pathways";
-        sc.sam_type_name.length = strlen(sc.sam_type_name.data);
-#if 1
-        sc.sam_challenge_label.data = "Enter the following on your keypad";
-        sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
-#endif
-        /* generate digit string, take it mod 1000000 (six digits.) */
-        {
-            int j;
-            krb5_keyblock session_key;
-            char outputblock[8];
-            int i;
-
-            session_key.contents = 0;
-
-            memset(inputblock, 0, 8);
-
-            retval = krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_CRC,
-                                            &session_key);
-
-            if (retval) {
-                /* random key failed */
-                kdc_err(kdc_context, retval,
-                        "generating random challenge for preauth");
-                return retval;
-            }
-            /* now session_key has a key which we can pick bits out of */
-            /* we need six decimal digits. Grab 6 bytes, div 2, mod 10 each. */
-            if (session_key.length != 8) {
-                kdc_err(kdc_context, retval = KRB5KDC_ERR_ETYPE_NOSUPP,
-                        "keytype didn't match code expectations");
-                return retval;
-            }
-            for(i = 0; i<6; i++) {
-                inputblock[i] = '0' + ((session_key.contents[i]/2) % 10);
-            }
-            if (session_key.contents)
-                krb5_free_keyblock_contents(kdc_context, &session_key);
-
-            /* retval = krb5_finish_key(kdc_context, &eblock); */
-            /* now we have inputblock containing the 8 byte input to DES... */
-            sc.sam_challenge.data = inputblock;
-            sc.sam_challenge.length = 6;
-
-            encrypting_key.enctype = ENCTYPE_DES_CBC_RAW;
-
-            if (retval)
-                kdc_err(kdc_context, retval, "snk4 processing key");
-
-            {
-                krb5_data plain;
-                krb5_enc_data cipher;
-
-                plain.length = 8;
-                plain.data = inputblock;
-
-                /* XXX I know this is enough because of the fixed raw enctype.
-                   if it's not, the underlying code will return a reasonable
-                   error, which should never happen */
-                cipher.ciphertext.length = 8;
-                cipher.ciphertext.data = outputblock;
-
-                if ((retval = krb5_c_encrypt(kdc_context, &encrypting_key,
-                                             /* XXX */ 0, 0, &plain, &cipher))) {
-                    kdc_err(kdc_context, retval,
-                            "snk4 response generation failed");
-                    return retval;
-                }
-            }
-
-            /* now output block is the raw bits of the response; convert it
-               to display form */
-            for (j=0; j<4; j++) {
-                char n[2];
-                int k;
-                n[0] = outputblock[j] & 0xf;
-                n[1] = (outputblock[j]>>4) & 0xf;
-                for (k=0; k<2; k++) {
-                    if(n[k] > 9) n[k] = ((n[k]-1)>>2);
-                    /* This is equivalent to:
-                       if(n[k]>=0xa && n[k]<=0xc) n[k] = 2;
-                       if(n[k]>=0xd && n[k]<=0xf) n[k] = 3;
-                    */
-                }
-                /* for v4, we keygen: *(j+(char*)&key1) = (n[1]<<4) | n[0]; */
-                /* for v5, we just generate a string */
-                response[2*j+0] = '0' + n[1];
-                response[2*j+1] = '0' + n[0];
-                /* and now, response has what we work with. */
-            }
-            response[8] = 0;
-            predict_response.data = response;
-            predict_response.length = 8;
-#if 0                           /* for debugging, hack the output too! */
-            sc.sam_challenge_label.data = response;
-            sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
-#endif
-        }
-
-        psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
-        /* string2key on sc.sam_challenge goes in here */
-        /* eblock is just to set the enctype */
-        {
-            retval = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
-                                          &predict_response, 0 /* salt */,
-                                          &psr.sam_key);
-            if (retval) goto cleanup;
-
-            retval = encode_krb5_predicted_sam_response(&psr, &scratch);
-            if (retval) goto cleanup;
-
-            {
-                size_t enclen;
-                krb5_enc_data tmpdata;
-
-                if ((retval = krb5_c_encrypt_length(context,
-                                                    psr_key.enctype,
-                                                    scratch->length, &enclen)))
-                    goto cleanup;
-
-                if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) {
-                    retval = ENOMEM;
-                    goto cleanup;
-                }
-                tmpdata.ciphertext.length = enclen;
-
-                if ((retval = krb5_c_encrypt(context, &psr_key,
-                                             /* XXX */ 0, 0, scratch, &tmpdata)))
-                    goto cleanup;
-
-                sc.sam_track_id = tmpdata.ciphertext;
-            }
-            if (retval) goto cleanup;
-        }
-
-        sc.sam_response_prompt.data = "Enter the displayed response";
-        sc.sam_response_prompt.length = strlen(sc.sam_response_prompt.data);
-        sc.sam_pk_for_sad.length = 0;
-        sc.sam_nonce = 0;
-        /* Generate checksum */
-        /*krb5_checksum_size(context, ctype)*/
-        /*krb5_calculate_checksum(context,ctype,in,in_length,seed,
-          seed_length,outcksum) */
-        /*krb5_verify_checksum(context,ctype,cksum,in,in_length,seed,
-          seed_length) */
-#if 0 /* XXX a) glue appears broken; b) this gives up the SAD */
-        sc.sam_cksum.contents = (krb5_octet *)
-            malloc(krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES));
-        if (sc.sam_cksum.contents == NULL) return(ENOMEM);
-
-        retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES,
-                                         sc.sam_challenge.data,
-                                         sc.sam_challenge.length,
-                                         psr.sam_key.contents, /* key */
-                                         psr.sam_key.length, /* key length */
-                                         &sc.sam_cksum);
-        if (retval) { free(sc.sam_cksum.contents); return(retval); }
-#endif /* 0 */
-
-        retval = encode_krb5_sam_challenge(&sc, &scratch);
-        if (retval) goto cleanup;
-        pa_data->magic = KV5M_PA_DATA;
-        pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE;
-        pa_data->contents = (krb5_octet *)scratch->data;
-        pa_data->length = scratch->length;
-
-        retval = 0;
-        break;
-    }
-
-cleanup:
-    krb5_free_keyblock_contents(context, &encrypting_key);
-    return retval;
-}
-
-static krb5_error_code
-verify_sam_response(krb5_context context, krb5_db_entry *client,
-                    krb5_data *req_pkt,
-                    krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
-                    krb5_pa_data *pa,
-                    preauth_get_entry_data_proc sam_get_entry_data,
-                    void *pa_system_context,
-                    void **pa_request_context,
-                    krb5_data **e_data,
-                    krb5_authdata ***authz_data)
-{
-    krb5_error_code             retval;
-    krb5_data                   scratch;
-    krb5_sam_response           *sr = 0;
-    krb5_predicted_sam_response *psr = 0;
-    krb5_enc_sam_response_enc   *esre = 0;
-    krb5_timestamp              timenow;
-    char                        *princ_req = 0, *princ_psr = 0;
-
-    scratch.data = (char *)pa->contents;
-    scratch.length = pa->length;
-
-    if ((retval = decode_krb5_sam_response(&scratch, &sr))) {
-        scratch.data = 0;
-        kdc_err(context, retval, "decode_krb5_sam_response failed");
-        goto cleanup;
-    }
 
-    /* XXX We can only handle the challenge/response model of SAM.
-       See passwords-04, par 4.1, 4.2 */
-    {
-        krb5_enc_data tmpdata;
-
-        tmpdata.enctype = ENCTYPE_UNKNOWN;
-        tmpdata.ciphertext = sr->sam_track_id;
-
-        scratch.length = tmpdata.ciphertext.length;
-        if ((scratch.data = (char *) malloc(scratch.length)) == NULL) {
-            retval = ENOMEM;
-            goto cleanup;
-        }
-
-        if ((retval = krb5_c_decrypt(context, &psr_key, /* XXX */ 0, 0,
-                                     &tmpdata, &scratch))) {
-            kdc_err(context, retval, "decrypt track_id failed");
-            goto cleanup;
-        }
-    }
-
-    if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) {
-        kdc_err(context, retval,
-                "decode_krb5_predicted_sam_response failed -- replay attack?");
-        goto cleanup;
-    }
-
-    /* Replay detection */
-    if ((retval = krb5_unparse_name(context, request->client, &princ_req)))
-        goto cleanup;
-    if ((retval = krb5_unparse_name(context, psr->client, &princ_psr)))
-        goto cleanup;
-    if (strcmp(princ_req, princ_psr) != 0) {
-        kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED,
-                "Principal mismatch in SAM psr! -- replay attack?");
-        goto cleanup;
-    }
-
-    if ((retval = krb5_timeofday(context, &timenow)))
-        goto cleanup;
-
-#ifdef USE_RCACHE
-    {
-        krb5_donot_replay rep;
-        extern krb5_deltat rc_lifetime;
-        /*
-         * Verify this response came back in a timely manner.
-         * We do this b/c otherwise very old (expunged from the rcache)
-         * psr's would be able to be replayed.
-         */
-        if (timenow - psr->stime > rc_lifetime) {
-            kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED,
-                    "SAM psr came back too late! -- replay attack?");
-            goto cleanup;
-        }
-
-        /* Now check the replay cache. */
-        rep.client = princ_psr;
-        rep.server = "SAM/rc";  /* Should not match any principal name. */
-        rep.msghash = NULL;
-        rep.ctime = psr->stime;
-        rep.cusec = psr->susec;
-        retval = krb5_rc_store(kdc_context, kdc_rcache, &rep);
-        if (retval) {
-            kdc_err(kdc_context, retval, "SAM psr replay attack!");
-            goto cleanup;
-        }
-    }
-#endif /* USE_RCACHE */
-
-
-    {
-        free(scratch.data);
-        scratch.length = sr->sam_enc_nonce_or_ts.ciphertext.length;
-        if ((scratch.data = (char *) malloc(scratch.length)) == NULL) {
-            retval = ENOMEM;
-            goto cleanup;
-        }
-
-        if ((retval = krb5_c_decrypt(context, &psr->sam_key, /* XXX */ 0,
-                                     0, &sr->sam_enc_nonce_or_ts, &scratch))) {
-            kdc_err(context, retval, "decrypt nonce_or_ts failed");
-            goto cleanup;
-        }
-    }
-
-    if ((retval = decode_krb5_enc_sam_response_enc(&scratch, &esre))) {
-        kdc_err(context, retval, "decode_krb5_enc_sam_response_enc failed");
-        goto cleanup;
-    }
-
-    if (esre->sam_timestamp != sr->sam_patimestamp) {
-        retval = KRB5KDC_ERR_PREAUTH_FAILED;
-        goto cleanup;
-    }
-
-    if (labs(timenow - sr->sam_patimestamp) > context->clockskew) {
-        retval = KRB5KRB_AP_ERR_SKEW;
-        goto cleanup;
-    }
-
-    setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH);
-
-cleanup:
-    if (retval)
-        kdc_err(context, retval, "sam verify failure");
-    if (scratch.data) free(scratch.data);
-    if (sr) free(sr);
-    if (psr) free(psr);
-    if (esre) free(esre);
-    if (princ_psr) free(princ_psr);
-    if (princ_req) free(princ_req);
-
-    return retval;
-}
 
 #if APPLE_PKINIT
 /* PKINIT preauth support */
index c07fc46da742567ce4141f19c343d7ae4df3ffcd..5d7d2448ce333a686f3241b00774767165efcc8c 100644 (file)
@@ -721,295 +721,6 @@ pa_enc_timestamp(krb5_context context, krb5_kdc_req *request,
     return(0);
 }
 
-static char *
-sam_challenge_banner(krb5_int32 sam_type)
-{
-    char *label;
-
-    switch (sam_type) {
-    case PA_SAM_TYPE_ENIGMA:    /* Enigma Logic */
-        label = "Challenge for Enigma Logic mechanism";
-        break;
-    case PA_SAM_TYPE_DIGI_PATH: /*  Digital Pathways */
-    case PA_SAM_TYPE_DIGI_PATH_HEX: /*  Digital Pathways */
-        label = "Challenge for Digital Pathways mechanism";
-        break;
-    case PA_SAM_TYPE_ACTIVCARD_DEC: /*  Digital Pathways */
-    case PA_SAM_TYPE_ACTIVCARD_HEX: /*  Digital Pathways */
-        label = "Challenge for Activcard mechanism";
-        break;
-    case PA_SAM_TYPE_SKEY_K0:   /*  S/key where  KDC has key 0 */
-        label = "Challenge for Enhanced S/Key mechanism";
-        break;
-    case PA_SAM_TYPE_SKEY:      /*  Traditional S/Key */
-        label = "Challenge for Traditional S/Key mechanism";
-        break;
-    case PA_SAM_TYPE_SECURID:   /*  Security Dynamics */
-        label = "Challenge for Security Dynamics mechanism";
-        break;
-    case PA_SAM_TYPE_SECURID_PREDICT:   /* predictive Security Dynamics */
-        label = "Challenge for Security Dynamics mechanism";
-        break;
-    default:
-        label = "Challenge from authentication server";
-        break;
-    }
-
-    return(label);
-}
-
-/* this macro expands to the int,ptr necessary for "%.*s" in an sprintf */
-
-#define SAMDATA(kdata, str, maxsize)                                    \
-    (int)((kdata.length)?                                               \
-          ((((kdata.length)<=(maxsize))?(kdata.length):strlen(str))):   \
-          strlen(str)),                                                 \
-        (kdata.length)?                                                 \
-        ((((kdata.length)<=(maxsize))?(kdata.data):(str))):(str)
-
-/* XXX Danger! This code is not in sync with the kerberos-password-02
-   draft.  This draft cannot be implemented as written.  This code is
-   compatible with earlier versions of mit krb5 and cygnus kerbnet. */
-
-static krb5_error_code
-pa_sam(krb5_context context, krb5_kdc_req *request, krb5_pa_data *in_padata,
-       krb5_pa_data **out_padata, krb5_data *salt, krb5_data *s2kparams,
-       krb5_enctype *etype, krb5_keyblock *as_key, krb5_prompter_fct prompter,
-       void *prompter_data, krb5_gic_get_as_key_fct gak_fct, void *gak_data)
-{
-    krb5_error_code             ret;
-    krb5_data                   tmpsam;
-    char                        name[100], banner[100];
-    char                        prompt[100], response[100];
-    krb5_data                   response_data;
-    krb5_prompt                 kprompt;
-    krb5_prompt_type            prompt_type;
-    krb5_data                   defsalt;
-    krb5_sam_challenge          *sam_challenge = 0;
-    krb5_sam_response           sam_response;
-    /* these two get encrypted and stuffed in to sam_response */
-    krb5_enc_sam_response_enc   enc_sam_response_enc;
-    krb5_data *                 scratch;
-    krb5_pa_data *              pa;
-
-    if (prompter == NULL)
-        return EIO;
-
-    tmpsam.length = in_padata->length;
-    tmpsam.data = (char *) in_padata->contents;
-    if ((ret = decode_krb5_sam_challenge(&tmpsam, &sam_challenge)))
-        return(ret);
-
-    if (sam_challenge->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) {
-        krb5_free_sam_challenge(context, sam_challenge);
-        return(KRB5_SAM_UNSUPPORTED);
-    }
-
-    /* If we need the password from the user (USE_SAD_AS_KEY not set),  */
-    /* then get it here.  Exception for "old" KDCs with CryptoCard      */
-    /* support which uses the USE_SAD_AS_KEY flag, but still needs pwd  */
-
-    if (!(sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) ||
-        (sam_challenge->sam_type == PA_SAM_TYPE_CRYPTOCARD)) {
-
-        /* etype has either been set by caller or by KRB5_PADATA_ETYPE_INFO */
-        /* message from the KDC.  If it is not set, pick an enctype that we */
-        /* think the KDC will have for us.                                  */
-
-        if (*etype == 0)
-            *etype = ENCTYPE_DES_CBC_CRC;
-
-        if ((ret = (gak_fct)(context, request->client, *etype, prompter,
-                             prompter_data, salt, s2kparams, as_key,
-                             gak_data))) {
-            krb5_free_sam_challenge(context, sam_challenge);
-            return(ret);
-        }
-        TRACE_PREAUTH_SAM_KEY_GAK(context, as_key);
-    }
-    snprintf(name, sizeof(name), "%.*s",
-             SAMDATA(sam_challenge->sam_type_name, "SAM Authentication",
-                     sizeof(name) - 1));
-
-    snprintf(banner, sizeof(banner), "%.*s",
-             SAMDATA(sam_challenge->sam_challenge_label,
-                     sam_challenge_banner(sam_challenge->sam_type),
-                     sizeof(banner)-1));
-
-    /* sprintf(prompt, "Challenge is [%s], %s: ", challenge, prompt); */
-    snprintf(prompt, sizeof(prompt), "%s%.*s%s%.*s",
-             sam_challenge->sam_challenge.length?"Challenge is [":"",
-             SAMDATA(sam_challenge->sam_challenge, "", 20),
-             sam_challenge->sam_challenge.length?"], ":"",
-             SAMDATA(sam_challenge->sam_response_prompt, "passcode", 55));
-
-    response_data.data = response;
-    response_data.length = sizeof(response);
-
-    kprompt.prompt = prompt;
-    kprompt.hidden = 1;
-    kprompt.reply = &response_data;
-    prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
-
-    /* PROMPTER_INVOCATION */
-    krb5int_set_prompt_types(context, &prompt_type);
-    if ((ret = ((*prompter)(context, prompter_data, name,
-                            banner, 1, &kprompt)))) {
-        krb5_free_sam_challenge(context, sam_challenge);
-        krb5int_set_prompt_types(context, 0);
-        return(ret);
-    }
-    krb5int_set_prompt_types(context, 0);
-
-    enc_sam_response_enc.sam_nonce = sam_challenge->sam_nonce;
-    if (sam_challenge->sam_nonce == 0) {
-        if ((ret = krb5_us_timeofday(context,
-                                     &enc_sam_response_enc.sam_timestamp,
-                                     &enc_sam_response_enc.sam_usec))) {
-            krb5_free_sam_challenge(context,sam_challenge);
-            return(ret);
-        }
-
-        sam_response.sam_patimestamp = enc_sam_response_enc.sam_timestamp;
-    }
-
-    /* XXX What if more than one flag is set?  */
-    if (sam_challenge->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) {
-
-        /* Most of this should be taken care of before we get here.  We */
-        /* will need the user's password and as_key to encrypt the SAD  */
-        /* and we want to preserve ordering of user prompts (first      */
-        /* password, then SAM data) so that user's won't be confused.   */
-
-        if (as_key->length) {
-            krb5_free_keyblock_contents(context, as_key);
-            as_key->length = 0;
-        }
-
-        /* generate a salt using the requested principal */
-
-        if ((salt->length == -1 || salt->length == SALT_TYPE_AFS_LENGTH) && (salt->data == NULL)) {
-            if ((ret = krb5_principal2salt(context, request->client,
-                                           &defsalt))) {
-                krb5_free_sam_challenge(context, sam_challenge);
-                return(ret);
-            }
-
-            salt = &defsalt;
-        } else {
-            defsalt.length = 0;
-        }
-
-        /* generate a key using the supplied password */
-
-        ret = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
-                                   (krb5_data *)gak_data, salt, as_key);
-
-        if (defsalt.length)
-            free(defsalt.data);
-
-        if (ret) {
-            krb5_free_sam_challenge(context, sam_challenge);
-            return(ret);
-        }
-
-        /* encrypt the passcode with the key from above */
-
-        enc_sam_response_enc.sam_sad = response_data;
-    } else if (sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) {
-
-        /* process the key as password */
-
-        if (as_key->length) {
-            krb5_free_keyblock_contents(context, as_key);
-            as_key->length = 0;
-        }
-
-#if 0
-        if ((salt->length == SALT_TYPE_AFS_LENGTH) && (salt->data == NULL)) {
-            if (ret = krb5_principal2salt(context, request->client,
-                                          &defsalt)) {
-                krb5_free_sam_challenge(context, sam_challenge);
-                return(ret);
-            }
-
-            salt = &defsalt;
-        } else {
-            defsalt.length = 0;
-        }
-#else
-        defsalt.length = 0;
-        salt = NULL;
-#endif
-
-        /* XXX As of the passwords-04 draft, no enctype is specified,
-           the server uses ENCTYPE_DES_CBC_MD5. In the future the
-           server should send a PA-SAM-ETYPE-INFO containing the enctype. */
-
-        ret = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
-                                   &response_data, salt, as_key);
-
-        if (defsalt.length)
-            free(defsalt.data);
-
-        if (ret) {
-            krb5_free_sam_challenge(context, sam_challenge);
-            return(ret);
-        }
-
-        enc_sam_response_enc.sam_sad.length = 0;
-    } else {
-        /* Eventually, combine SAD with long-term key to get
-           encryption key.  */
-        krb5_free_sam_challenge(context, sam_challenge);
-        return KRB5_PREAUTH_BAD_TYPE;
-    }
-
-    /* copy things from the challenge */
-    sam_response.sam_nonce = sam_challenge->sam_nonce;
-    sam_response.sam_flags = sam_challenge->sam_flags;
-    sam_response.sam_track_id = sam_challenge->sam_track_id;
-    sam_response.sam_type = sam_challenge->sam_type;
-    sam_response.magic = KV5M_SAM_RESPONSE;
-
-    krb5_free_sam_challenge(context, sam_challenge);
-
-    /* encode the encoded part of the response */
-    if ((ret = encode_krb5_enc_sam_response_enc(&enc_sam_response_enc,
-                                                &scratch)))
-        return(ret);
-
-    ret = krb5_encrypt_helper(context, as_key, 0, scratch,
-                              &sam_response.sam_enc_nonce_or_ts);
-
-    krb5_free_data(context, scratch);
-
-    if (ret)
-        return(ret);
-
-    /* sam_enc_key is reserved for future use */
-    sam_response.sam_enc_key.ciphertext.length = 0;
-
-    if ((pa = malloc(sizeof(krb5_pa_data))) == NULL)
-        return(ENOMEM);
-
-    if ((ret = encode_krb5_sam_response(&sam_response, &scratch))) {
-        free(pa);
-        return(ret);
-    }
-
-    pa->magic = KV5M_PA_DATA;
-    pa->pa_type = KRB5_PADATA_SAM_RESPONSE;
-    pa->length = scratch->length;
-    pa->contents = (krb5_octet *) scratch->data;
-
-    *out_padata = pa;
-
-    free(scratch);
-
-    return(0);
-}
-
 #if APPLE_PKINIT
 /*
  * PKINIT. One function to generate AS-REQ, one to parse AS-REP
@@ -1324,6 +1035,51 @@ error_out:
 }
 #endif /* APPLE_PKINIT */
 
+/* this macro expands to the int,ptr necessary for "%.*s" in an sprintf */
+
+#define SAMDATA(kdata, str, maxsize)                                    \
+    (int)((kdata.length)?                                               \
+          ((((kdata.length)<=(maxsize))?(kdata.length):strlen(str))):   \
+          strlen(str)),                                                 \
+        (kdata.length)?                                                 \
+        ((((kdata.length)<=(maxsize))?(kdata.data):(str))):(str)
+static char *
+sam_challenge_banner(krb5_int32 sam_type)
+{
+    char *label;
+
+    switch (sam_type) {
+    case PA_SAM_TYPE_ENIGMA:    /* Enigma Logic */
+        label = "Challenge for Enigma Logic mechanism";
+        break;
+    case PA_SAM_TYPE_DIGI_PATH: /*  Digital Pathways */
+    case PA_SAM_TYPE_DIGI_PATH_HEX: /*  Digital Pathways */
+        label = "Challenge for Digital Pathways mechanism";
+        break;
+    case PA_SAM_TYPE_ACTIVCARD_DEC: /*  Digital Pathways */
+    case PA_SAM_TYPE_ACTIVCARD_HEX: /*  Digital Pathways */
+        label = "Challenge for Activcard mechanism";
+        break;
+    case PA_SAM_TYPE_SKEY_K0:   /*  S/key where  KDC has key 0 */
+        label = "Challenge for Enhanced S/Key mechanism";
+        break;
+    case PA_SAM_TYPE_SKEY:      /*  Traditional S/Key */
+        label = "Challenge for Traditional S/Key mechanism";
+        break;
+    case PA_SAM_TYPE_SECURID:   /*  Security Dynamics */
+        label = "Challenge for Security Dynamics mechanism";
+        break;
+    case PA_SAM_TYPE_SECURID_PREDICT:   /* predictive Security Dynamics */
+        label = "Challenge for Security Dynamics mechanism";
+        break;
+    default:
+        label = "Challenge from authentication server";
+        break;
+    }
+
+    return(label);
+}
+
 static krb5_error_code
 pa_sam_2(krb5_context context, krb5_kdc_req *request, krb5_pa_data *in_padata,
          krb5_pa_data **out_padata, krb5_data *salt, krb5_data *s2kparams,
@@ -1439,7 +1195,7 @@ pa_sam_2(krb5_context context, krb5_kdc_req *request, krb5_pa_data *in_padata,
     krb5int_set_prompt_types(context, (krb5_prompt_type *)NULL);
 
     /* Generate salt used by string_to_key() */
-    if ((salt->length == -1) && (salt->data == NULL)) {
+    if (((int) salt->length == -1) && (salt->data == NULL)) {
         if ((retval =
              krb5_principal2salt(context, request->client, &defsalt))) {
             krb5_free_sam_challenge_2(context, sc2);
@@ -1725,11 +1481,6 @@ static const pa_types_t pa_types[] = {
         pa_sam_2,
         PA_REAL,
     },
-    {
-        KRB5_PADATA_SAM_CHALLENGE,
-        pa_sam,
-        PA_REAL,
-    },
     {
         KRB5_PADATA_FX_COOKIE,
         pa_fx_cookie,