1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * plugins/preauth/securid_sam2/securid_sam2_main.c
5 * Copyright (C) 2009, 2010 by the Massachusetts Institute of Technology.
8 * Export of this software from the United States of America may
9 * require a specific license from the United States Government.
10 * It is the responsibility of any person or organization contemplating
11 * export to obtain such a license before exporting.
13 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14 * distribute this software and its documentation for any purpose and
15 * without fee is hereby granted, provided that the above copyright
16 * notice appear in all copies and that both that copyright notice and
17 * this permission notice appear in supporting documentation, and that
18 * the name of M.I.T. not be used in advertising or publicity pertaining
19 * to distribution of the software without specific, written prior
20 * permission. Furthermore if you modify this software you must label
21 * your software as modified software and not distribute it in such a
22 * fashion that it might be confused with the original M.I.T. software.
23 * M.I.T. makes no representations about the suitability of
24 * this software for any purpose. It is provided "as is" without express
25 * or implied warranty.
27 * Copyright (c) 2002 Naval Research Laboratory (NRL/CCS)
29 * Permission to use, copy, modify and distribute this software and its
30 * documentation is hereby granted, provided that both the copyright
31 * notice and this permission notice appear in all copies of the software,
32 * derivative works or modified versions, and any portions thereof.
34 * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
35 * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
36 * RESULTING FROM THE USE OF THIS SOFTWARE.
41 #include <krb5/preauth_plugin.h>
48 } *sam_ptr, sam_inst_map[] = {
49 { "SECURID", PA_SAM_TYPE_SECURID, },
50 { "GRAIL", PA_SAM_TYPE_GRAIL, },
55 sam_get_db_entry(krb5_context context, krb5_principal client,
56 int *sam_type, struct _krb5_db_entry_new **db_entry)
58 struct _krb5_db_entry_new *assoc = NULL;
59 krb5_principal newp = NULL;
62 krb5_error_code retval;
66 retval = krb5_copy_principal(context, client, &newp);
68 krb5_set_error_message(context, retval,
69 "copying client name for preauth probe");
73 probeslot = krb5_princ_size(context, newp)++;
74 ptr = realloc(krb5_princ_name(context, newp),
75 krb5_princ_size(context, newp) * sizeof(krb5_data));
80 krb5_princ_name(context, newp) = ptr;
82 for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) {
83 if (*sam_type && *sam_type != sam_ptr->sam_type)
86 krb5_princ_component(context,newp,probeslot)->data = sam_ptr->name;
87 krb5_princ_component(context,newp,probeslot)->length =
88 strlen(sam_ptr->name);
89 retval = krb5_db_get_principal(context, newp, 0, &assoc);
95 krb5_princ_component(context,newp,probeslot)->data = 0;
96 krb5_princ_component(context,newp,probeslot)->length = 0;
97 krb5_free_principal(context, newp);
100 krb5_princ_size(context, newp)--;
103 if (sam_ptr->sam_type) {
104 /* Found entry of type sam_ptr->sam_type */
106 *sam_type = sam_ptr->sam_type;
110 krb5_db_free_principal(context, assoc);
113 return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
117 static krb5_error_code
118 kdc_include_padata(krb5_context context, krb5_kdc_req *request,
119 struct _krb5_db_entry_new *client,
120 struct _krb5_db_entry_new *server,
121 preauth_get_entry_data_proc get_entry_proc,
122 void *pa_module_context, krb5_pa_data *pa_data)
124 krb5_error_code retval;
125 krb5_sam_challenge_2 sc2;
126 krb5_sam_challenge_2_body sc2b;
127 int sam_type = 0; /* unknown */
128 krb5_db_entry *sam_db_entry = NULL;
129 krb5_data *encoded_challenge = NULL;
131 memset(&sc2, 0, sizeof(sc2));
132 memset(&sc2b, 0, sizeof(sc2b));
133 sc2b.magic = KV5M_SAM_CHALLENGE_2;
134 sc2b.sam_type = sam_type;
136 retval = sam_get_db_entry(context, client->princ, &sam_type,
142 retval = KRB5_PREAUTH_BAD_TYPE;
147 * Defer getting the key for the SAM principal associated with the client
148 * until the mechanism-specific code. The mechanism may want to get a
153 #ifdef ARL_SECURID_PREAUTH
154 case PA_SAM_TYPE_SECURID:
155 retval = get_securid_edata_2(context, client, &sc2b, &sc2);
159 retval = encode_krb5_sam_challenge_2(&sc2, &encoded_challenge);
161 krb5_set_error_message(context, retval,
162 "while encoding SECURID SAM_CHALLENGE_2");
166 pa_data->magic = KV5M_PA_DATA;
167 pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
168 pa_data->contents = (krb5_octet *) encoded_challenge->data;
169 pa_data->length = encoded_challenge->length;
170 encoded_challenge->data = NULL;
174 #endif /* ARL_SECURID_PREAUTH */
176 retval = KRB5_PREAUTH_BAD_TYPE;
181 krb5_free_data(context, encoded_challenge);
183 krb5_db_free_principal(context, sam_db_entry);
187 static krb5_error_code
188 kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client,
189 krb5_data *req_pkt, krb5_kdc_req *request,
190 krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa_data,
191 preauth_get_entry_data_proc get_entry_proc,
192 void *pa_module_context, void **opaque,
193 krb5_data **e_data, krb5_authdata ***authz_data)
195 krb5_error_code retval;
196 krb5_sam_response_2 *sr2 = NULL;
197 krb5_data scratch, *scratch2;
198 char *client_name = NULL;
199 krb5_sam_challenge_2 *out_sc2 = NULL;
201 scratch.data = (char *) pa_data->contents;
202 scratch.length = pa_data->length;
204 retval = krb5_unparse_name(context, client->princ, &client_name);
208 retval = decode_krb5_sam_response_2(&scratch, &sr2);
210 krb5_set_error_message(context, retval, "while decoding "
211 "SAM_RESPONSE_2 in verify_sam_response_2");
216 switch (sr2->sam_type) {
217 #ifdef ARL_SECURID_PREAUTH
218 case PA_SAM_TYPE_SECURID:
219 retval = verify_securid_data_2(context, client, sr2, enc_tkt_reply,
224 #endif /* ARL_SECURID_PREAUTH */
226 retval = KRB5_PREAUTH_BAD_TYPE;
227 krb5_set_error_message(context, retval, "while verifying SAM 2 data");
232 * It is up to the method-specific verify routine to set the ticket flags to
233 * indicate TKT_FLG_HW_AUTH and/or TKT_FLG_PRE_AUTH. Some methods may
234 * require more than one round of dialog with the client and must return
235 * successfully from their verify routine. If does not set the TGT flags,
236 * the required_preauth conditions will not be met and it will try again to
237 * get enough preauth data from the client. Do not set TGT flags here.
240 /*Note that e_data is an output even in error conditions.*/
243 krb5_pa_data *pa_array[2];
244 pa_array[0] = &pa_out;
246 pa_out.pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
247 retval = encode_krb5_sam_challenge_2(out_sc2, &scratch2);
248 krb5_free_sam_challenge_2(context, out_sc2);
251 pa_out.contents = (krb5_octet *) scratch2->data;
252 pa_out.length = scratch2->length;
253 retval = encode_krb5_padata_sequence(pa_array, e_data);
254 krb5_free_data(context, scratch2);
257 krb5_free_sam_response_2(context, sr2);
264 kdc_preauth_flags(krb5_context context, krb5_preauthtype patype)
269 krb5_preauthtype supported_pa_types[] = {
270 KRB5_PADATA_SAM_RESPONSE_2, 0};
272 struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = {
274 &supported_pa_types[0],