Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/plugins/preauth/securid_sam2/securid2.c
34907 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* plugins/preauth/securid_sam2/securid2.c */
3
/*
4
* Copyright (C) 2010 by the Massachusetts Institute of Technology.
5
* All rights reserved.
6
*
7
* Export of this software from the United States of America may
8
* require a specific license from the United States Government.
9
* It is the responsibility of any person or organization contemplating
10
* export to obtain such a license before exporting.
11
*
12
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
* distribute this software and its documentation for any purpose and
14
* without fee is hereby granted, provided that the above copyright
15
* notice appear in all copies and that both that copyright notice and
16
* this permission notice appear in supporting documentation, and that
17
* the name of M.I.T. not be used in advertising or publicity pertaining
18
* to distribution of the software without specific, written prior
19
* permission. Furthermore if you modify this software you must label
20
* your software as modified software and not distribute it in such a
21
* fashion that it might be confused with the original M.I.T. software.
22
* M.I.T. makes no representations about the suitability of
23
* this software for any purpose. It is provided "as is" without express
24
* or implied warranty.
25
*/
26
/*
27
* Copyright (c) 2002 Naval Research Laboratory (NRL/CCS)
28
*
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.
33
*
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.
37
*/
38
39
#ifdef ARL_SECURID_PREAUTH
40
41
#include "k5-int.h"
42
#include <kdb.h>
43
#include <stdio.h>
44
#include <adm_proto.h>
45
#include <syslog.h>
46
#include <acexport.h>
47
#include <sdi_defs.h>
48
#include "extern.h"
49
50
#define KRB5_SAM_SECURID_NEXT_CHALLENGE_MAGIC 0x5ec1d000
51
struct securid_track_data {
52
SDI_HANDLE handle;
53
char state;
54
char passcode[LENPRNST+1];
55
long hostid;
56
};
57
58
#define SECURID_STATE_NEW_PIN 1 /* Ask for a new pin */
59
#define SECURID_STATE_NEW_PIN_AGAIN 2 /* Ask for new pin again */
60
#define SECURID_STATE_NEXT_CODE 3 /* Ask for the next pin code */
61
#define SECURID_STATE_INITIAL 4
62
63
static char *PASSCODE_message = "SecurID Passcode";
64
static char *NEXT_PASSCODE_message = "Next Passcode";
65
static char *NEW_PIN_AGAIN_message = "New PIN Again";
66
static char PIN_message[64]; /* Max length should be 50 chars */
67
68
/*
69
* krb5_error_code get_securid_key():
70
* inputs: context: from KDC process
71
* client: database entry of client executing
72
* SecurID SAM preauthentication
73
* outputs: client_securid_key: pointer to krb5_keyblock
74
* which is key for the client's SecurID
75
* database entry.
76
* returns: 0 on success
77
* KRB5 error codes otherwise
78
*
79
* builds principal name with final instance of "SECURID" and
80
* finds the database entry, decrypts the key out of the database
81
* and passes the key back to the calling process
82
*/
83
84
static krb5_error_code
85
get_securid_key(krb5_context context, krb5_db_entry *client,
86
krb5_keyblock *client_securid_key)
87
{
88
krb5_db_entry *sam_securid_entry = NULL;
89
krb5_key_data *client_securid_key_data = NULL;
90
int sam_type = PA_SAM_TYPE_SECURID;
91
krb5_error_code retval = 0;
92
93
if (!client_securid_key)
94
return KRB5_PREAUTH_NO_KEY;
95
96
retval = sam_get_db_entry(context, client->princ,
97
&sam_type, &sam_securid_entry);
98
if (retval)
99
return KRB5_PREAUTH_NO_KEY;
100
101
/* Find key with key_type = salt_type = kvno = -1. This finds the */
102
/* latest kvno in the list. */
103
104
retval = krb5_dbe_find_enctype(context, sam_securid_entry,
105
-1, -1, -1, &client_securid_key_data);
106
if (retval) {
107
com_err("krb5kdc", retval,
108
"while getting key from client's SAM SecurID entry");
109
goto cleanup;
110
}
111
retval = krb5_dbe_decrypt_key_data(context, NULL, client_securid_key_data,
112
client_securid_key, NULL);
113
if (retval) {
114
com_err("krb5kdc", retval,
115
"while decrypting key from client's SAM SecurID entry");
116
goto cleanup;
117
}
118
cleanup:
119
if (sam_securid_entry)
120
krb5_db_free_principal(context, sam_securid_entry);
121
return retval;
122
}
123
124
static krb5_error_code
125
securid_decrypt_track_data_2(krb5_context context, krb5_db_entry *client,
126
krb5_data *enc_track_data, krb5_data *output)
127
{
128
krb5_error_code retval;
129
krb5_keyblock sam_key;
130
krb5_enc_data tmp_enc_data;
131
sam_key.contents = NULL;
132
133
retval = get_securid_key(context, client, &sam_key);
134
if (retval != 0)
135
return retval;
136
137
tmp_enc_data.ciphertext = *enc_track_data;
138
tmp_enc_data.enctype = ENCTYPE_UNKNOWN;
139
tmp_enc_data.kvno = 0;
140
141
output->length = tmp_enc_data.ciphertext.length;
142
free(output->data);
143
output->data = k5alloc(output->length, &retval);
144
if (output->data == NULL)
145
goto cleanup;
146
retval = krb5_c_decrypt(context, &sam_key,
147
KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0,
148
&tmp_enc_data, output);
149
cleanup:
150
krb5_free_keyblock_contents(context, &sam_key);
151
152
if (retval) {
153
output->length = 0;
154
free(output->data);
155
output->data = NULL;
156
return retval;
157
}
158
159
return 0;
160
}
161
162
static krb5_error_code
163
securid_encrypt_track_data_2(krb5_context context, krb5_db_entry *client,
164
krb5_data *track_data, krb5_data *output)
165
{
166
krb5_error_code retval;
167
size_t olen;
168
krb5_keyblock sam_key;
169
krb5_enc_data tmp_enc_data;
170
171
output->data = NULL;
172
173
retval = get_securid_key(context,client, &sam_key);
174
if (retval != 0)
175
return retval;
176
177
retval = krb5_c_encrypt_length(context, sam_key.enctype,
178
track_data->length, &olen);
179
if (retval != 0)
180
goto cleanup;
181
assert(olen <= 65536);
182
output->length = olen;
183
output->data = k5alloc(output->length, &retval);
184
if (retval)
185
goto cleanup;
186
tmp_enc_data.ciphertext = *output;
187
tmp_enc_data.enctype = sam_key.enctype;
188
tmp_enc_data.kvno = 0;
189
190
retval = krb5_c_encrypt(context, &sam_key,
191
KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0,
192
track_data, &tmp_enc_data);
193
cleanup:
194
krb5_free_keyblock_contents(context, &sam_key);
195
196
if (retval) {
197
output->length = 0;
198
free(output->data);
199
output->data = NULL;
200
return retval;
201
}
202
return 0;
203
}
204
205
206
krb5_error_code
207
get_securid_edata_2(krb5_context context, krb5_db_entry *client,
208
krb5_keyblock *client_key, krb5_sam_challenge_2 *sc2)
209
{
210
krb5_error_code retval;
211
krb5_data scratch, track_id = empty_data();
212
char *user = NULL;
213
char *def_user = "<unknown user>";
214
struct securid_track_data sid_track_data;
215
krb5_data tmp_data;
216
krb5_sam_challenge_2_body sc2b;
217
218
scratch.data = NULL;
219
220
retval = krb5_unparse_name(context, client->princ, &user);
221
if (retval)
222
goto cleanup;
223
224
memset(&sc2b, 0, sizeof(sc2b));
225
sc2b.magic = KV5M_SAM_CHALLENGE_2;
226
sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
227
sc2b.sam_type_name.length = 0;
228
sc2b.sam_challenge_label.length = 0;
229
sc2b.sam_challenge.length = 0;
230
sc2b.sam_response_prompt.data = PASSCODE_message;
231
sc2b.sam_response_prompt.length = strlen(sc2b.sam_response_prompt.data);
232
sc2b.sam_pk_for_sad.length = 0;
233
sc2b.sam_type = PA_SAM_TYPE_SECURID;
234
235
sid_track_data.state = SECURID_STATE_INITIAL;
236
sid_track_data.hostid = gethostid();
237
tmp_data.data = (char *)&sid_track_data;
238
tmp_data.length = sizeof(sid_track_data);
239
retval = securid_encrypt_track_data_2(context, client, &tmp_data,
240
&track_id);
241
if (retval != 0) {
242
com_err("krb5kdc", retval, "while encrypting nonce track data");
243
goto cleanup;
244
}
245
sc2b.sam_track_id = track_id;
246
247
scratch.data = (char *)&sc2b.sam_nonce;
248
scratch.length = sizeof(sc2b.sam_nonce);
249
retval = krb5_c_random_make_octets(context, &scratch);
250
if (retval) {
251
com_err("krb5kdc", retval,
252
"while generating nonce data in get_securid_edata_2 (%s)",
253
user ? user : def_user);
254
goto cleanup;
255
}
256
257
/* Get the client's key */
258
sc2b.sam_etype = client_key->enctype;
259
260
retval = sam_make_challenge(context, &sc2b, client_key, sc2);
261
if (retval) {
262
com_err("krb5kdc", retval,
263
"while making SAM_CHALLENGE_2 checksum (%s)",
264
user ? user : def_user);
265
}
266
267
cleanup:
268
free(user);
269
krb5_free_data_contents(context, &track_id);
270
return retval;
271
}
272
273
krb5_error_code
274
verify_securid_data_2(krb5_context context, krb5_db_entry *client,
275
krb5_sam_response_2 *sr2,
276
krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa,
277
krb5_sam_challenge_2 **sc2_out)
278
{
279
krb5_error_code retval;
280
int new_pin = 0;
281
krb5_key_data *client_key_data = NULL;
282
krb5_keyblock client_key;
283
krb5_data scratch;
284
krb5_enc_sam_response_enc_2 *esre2 = NULL;
285
struct securid_track_data sid_track_data, *trackp = NULL;
286
krb5_data tmp_data;
287
SDI_HANDLE sd_handle = SDI_HANDLE_NONE;
288
krb5_sam_challenge_2 *sc2p = NULL;
289
char *cp, *user = NULL;
290
char *securid_user = NULL;
291
char passcode[LENPRNST+1];
292
char max_pin_len, min_pin_len, alpha_pin;
293
294
memset(&client_key, 0, sizeof(client_key));
295
memset(&scratch, 0, sizeof(scratch));
296
*sc2_out = NULL;
297
298
retval = krb5_unparse_name(context, client->princ, &user);
299
if (retval != 0) {
300
com_err("krb5kdc", retval,
301
"while unparsing client name in verify_securid_data_2");
302
return retval;
303
}
304
305
if ((sr2->sam_enc_nonce_or_sad.ciphertext.data == NULL) ||
306
(sr2->sam_enc_nonce_or_sad.ciphertext.length <= 0)) {
307
retval = KRB5KDC_ERR_PREAUTH_FAILED;
308
k5_setmsg(context, retval,
309
"No preauth data supplied in verify_securid_data_2 (%s)",
310
user);
311
goto cleanup;
312
}
313
314
retval = krb5_dbe_find_enctype(context, client,
315
sr2->sam_enc_nonce_or_sad.enctype, -1,
316
sr2->sam_enc_nonce_or_sad.kvno,
317
&client_key_data);
318
if (retval) {
319
com_err("krb5kdc", retval,
320
"while getting client key in verify_securid_data_2 (%s)",
321
user);
322
goto cleanup;
323
}
324
325
retval = krb5_dbe_decrypt_key_data(context, NULL, client_key_data,
326
&client_key, NULL);
327
if (retval != 0) {
328
com_err("krb5kdc", retval,
329
"while decrypting client key in verify_securid_data_2 (%s)",
330
user);
331
goto cleanup;
332
}
333
334
scratch.length = sr2->sam_enc_nonce_or_sad.ciphertext.length;
335
scratch.data = k5alloc(scratch.length, &retval);
336
if (retval)
337
goto cleanup;
338
retval = krb5_c_decrypt(context, &client_key,
339
KRB5_KEYUSAGE_PA_SAM_RESPONSE, 0,
340
&sr2->sam_enc_nonce_or_sad, &scratch);
341
if (retval) {
342
com_err("krb5kdc", retval,
343
"while decrypting SAD in verify_securid_data_2 (%s)", user);
344
goto cleanup;
345
}
346
347
retval = decode_krb5_enc_sam_response_enc_2(&scratch, &esre2);
348
if (retval) {
349
com_err("krb5kdc", retval,
350
"while decoding SAD in verify_securid_data_2 (%s)", user);
351
esre2 = NULL;
352
goto cleanup;
353
}
354
355
if (sr2->sam_nonce != esre2->sam_nonce) {
356
com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED,
357
"while checking nonce in verify_securid_data_2 (%s)", user);
358
retval = KRB5KDC_ERR_PREAUTH_FAILED;
359
goto cleanup;
360
}
361
362
if (esre2->sam_sad.length == 0 || esre2->sam_sad.data == NULL) {
363
com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED,
364
"No SecurID passcode in verify_securid_data_2 (%s)", user);
365
retval = KRB5KDC_ERR_PREAUTH_FAILED;
366
goto cleanup;
367
}
368
369
/* Copy out SAD to null-terminated buffer */
370
memset(passcode, 0, sizeof(passcode));
371
if (esre2->sam_sad.length > (sizeof(passcode) - 1)) {
372
retval = KRB5KDC_ERR_PREAUTH_FAILED;
373
com_err("krb5kdc", retval,
374
"SecurID passcode/PIN too long (%d bytes) in "
375
"verify_securid_data_2 (%s)",
376
esre2->sam_sad.length, user);
377
goto cleanup;
378
}
379
if (esre2->sam_sad.length > 0)
380
memcpy(passcode, esre2->sam_sad.data, esre2->sam_sad.length);
381
382
securid_user = strdup(user);
383
if (!securid_user) {
384
retval = ENOMEM;
385
com_err("krb5kdc", ENOMEM,
386
"while copying user name in verify_securid_data_2 (%s)", user);
387
goto cleanup;
388
}
389
cp = strchr(securid_user, '@');
390
if (cp != NULL)
391
*cp = '\0';
392
393
/* Check for any track_id data that may have state from a previous attempt
394
* at SecurID authentication. */
395
396
if (sr2->sam_track_id.data && (sr2->sam_track_id.length > 0)) {
397
krb5_data track_id_data;
398
399
memset(&track_id_data, 0, sizeof(track_id_data));
400
retval = securid_decrypt_track_data_2(context, client,
401
&sr2->sam_track_id,
402
&track_id_data);
403
if (retval) {
404
com_err("krb5kdc", retval,
405
"while decrypting SecurID trackID in "
406
"verify_securid_data_2 (%s)", user);
407
goto cleanup;
408
}
409
if (track_id_data.length < sizeof (struct securid_track_data)) {
410
retval = KRB5KDC_ERR_PREAUTH_FAILED;
411
com_err("krb5kdc", retval, "Length of track data incorrect");
412
goto cleanup;
413
}
414
trackp = (struct securid_track_data *)track_id_data.data;
415
416
if(trackp->hostid != gethostid()) {
417
krb5_klog_syslog(LOG_INFO, "Unexpected challenge response");
418
retval = KRB5KDC_ERR_DISCARD;
419
goto cleanup;
420
}
421
422
switch(trackp->state) {
423
case SECURID_STATE_INITIAL:
424
goto initial;
425
break;
426
case SECURID_STATE_NEW_PIN_AGAIN:
427
{
428
int pin1_len, pin2_len;
429
430
trackp->handle = ntohl(trackp->handle);
431
pin2_len = strlen(passcode);
432
pin1_len = strlen(trackp->passcode);
433
434
if ((pin1_len != pin2_len) ||
435
(memcmp(passcode, trackp->passcode, pin1_len) != 0)) {
436
retval = KRB5KDC_ERR_PREAUTH_FAILED;
437
krb5_klog_syslog(LOG_INFO, "New SecurID PIN Failed for user "
438
"%s: PIN mismatch", user);
439
break;
440
}
441
retval = SD_Pin(trackp->handle, passcode);
442
SD_Close(trackp->handle);
443
if (retval == ACM_NEW_PIN_ACCEPTED) {
444
enc_tkt_reply->flags|= TKT_FLG_HW_AUTH;
445
enc_tkt_reply->flags|= TKT_FLG_PRE_AUTH;
446
krb5_klog_syslog(LOG_INFO, "SecurID PIN Accepted for %s in "
447
"verify_securid_data_2",
448
securid_user);
449
retval = 0;
450
} else {
451
retval = KRB5KDC_ERR_PREAUTH_FAILED;
452
krb5_klog_syslog(LOG_INFO,
453
"SecurID PIN Failed for user %s (AceServer "
454
"returns %d) in verify_securid_data_2",
455
user, retval);
456
}
457
break;
458
}
459
case SECURID_STATE_NEW_PIN: {
460
krb5_sam_challenge_2_body sc2b;
461
sc2p = k5alloc(sizeof *sc2p, &retval);
462
if (retval)
463
goto cleanup;
464
memset(sc2p, 0, sizeof(*sc2p));
465
memset(&sc2b, 0, sizeof(sc2b));
466
sc2b.sam_type = PA_SAM_TYPE_SECURID;
467
sc2b.sam_response_prompt.data = NEW_PIN_AGAIN_message;
468
sc2b.sam_response_prompt.length =
469
strlen(sc2b.sam_response_prompt.data);
470
sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
471
sc2b.sam_etype = client_key.enctype;
472
473
tmp_data.data = (char *)&sc2b.sam_nonce;
474
tmp_data.length = sizeof(sc2b.sam_nonce);
475
if ((retval = krb5_c_random_make_octets(context, &tmp_data))) {
476
com_err("krb5kdc", retval,
477
"while making nonce for SecurID new "
478
"PIN2 SAM_CHALLENGE_2 (%s)", user);
479
goto cleanup;
480
}
481
sid_track_data.state = SECURID_STATE_NEW_PIN_AGAIN;
482
sid_track_data.handle = trackp->handle;
483
sid_track_data.hostid = gethostid();
484
/* Should we complain if sizes don't work ?? */
485
memcpy(sid_track_data.passcode, passcode,
486
sizeof(sid_track_data.passcode));
487
tmp_data.data = (char *)&sid_track_data;
488
tmp_data.length = sizeof(sid_track_data);
489
if ((retval = securid_encrypt_track_data_2(context, client,
490
&tmp_data,
491
&sc2b.sam_track_id))) {
492
com_err("krb5kdc", retval,
493
"while encrypting NEW PIN2 SecurID "
494
"track data for SAM_CHALLENGE_2 (%s)",
495
securid_user);
496
goto cleanup;
497
}
498
retval = sam_make_challenge(context, &sc2b, &client_key, sc2p);
499
if (retval) {
500
com_err("krb5kdc", retval,
501
"while making cksum for "
502
"SAM_CHALLENGE_2 (new PIN2) (%s)", securid_user);
503
goto cleanup;
504
}
505
krb5_klog_syslog(LOG_INFO,
506
"Requesting verification of new PIN for user %s",
507
securid_user);
508
*sc2_out = sc2p;
509
sc2p = NULL;
510
/*sc2_out may be set even on error path*/
511
retval = KRB5KDC_ERR_PREAUTH_REQUIRED;
512
goto cleanup;
513
}
514
case SECURID_STATE_NEXT_CODE:
515
trackp->handle = ntohl(trackp->handle);
516
retval = SD_Next(trackp->handle, passcode);
517
SD_Close(trackp->handle);
518
if (retval == ACM_OK) {
519
enc_tkt_reply->flags |= TKT_FLG_HW_AUTH | TKT_FLG_PRE_AUTH;
520
521
krb5_klog_syslog(LOG_INFO, "Next SecurID Code Accepted for "
522
"user %s", securid_user);
523
retval = 0;
524
} else {
525
krb5_klog_syslog(LOG_INFO, "Next SecurID Code Failed for user "
526
"%s (AceServer returns %d) in "
527
"verify_securid_data_2", user, retval);
528
retval = KRB5KDC_ERR_PREAUTH_FAILED;
529
}
530
break;
531
}
532
} else { /* No track data, this is first of N attempts */
533
initial:
534
retval = SD_Init(&sd_handle);
535
if (retval) {
536
com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED,
537
"SD_Init() returns error %d in verify_securid_data_2 (%s)",
538
retval, securid_user);
539
retval = KRB5KDC_ERR_PREAUTH_FAILED;
540
goto cleanup;
541
}
542
543
retval = SD_Lock(sd_handle, securid_user);
544
if (retval != ACM_OK) {
545
SD_Close(sd_handle);
546
retval = KRB5KDC_ERR_PREAUTH_FAILED;
547
krb5_klog_syslog(LOG_INFO,
548
"SD_Lock() failed (AceServer returns %d) for %s",
549
retval, securid_user);
550
goto cleanup;
551
}
552
553
retval = SD_Check(sd_handle, passcode, securid_user);
554
switch (retval) {
555
case ACM_OK:
556
SD_Close(sd_handle);
557
enc_tkt_reply->flags|= TKT_FLG_HW_AUTH;
558
enc_tkt_reply->flags|= TKT_FLG_PRE_AUTH;
559
krb5_klog_syslog(LOG_INFO, "SecurID passcode accepted for user %s",
560
user);
561
retval = 0;
562
break;
563
case ACM_ACCESS_DENIED:
564
SD_Close(sd_handle);
565
retval = KRB5KDC_ERR_PREAUTH_FAILED;
566
krb5_klog_syslog(LOG_INFO, "AceServer returns Access Denied for "
567
"user %s (SAM2)", user);
568
goto cleanup;
569
case ACM_NEW_PIN_REQUIRED:
570
new_pin = 1;
571
/*fall through*/
572
case ACM_NEXT_CODE_REQUIRED: {
573
krb5_sam_challenge_2_body sc2b;
574
sc2p = k5alloc(sizeof *sc2p, &retval);
575
if (retval)
576
goto cleanup;
577
578
memset(sc2p, 0, sizeof(*sc2p));
579
memset(&sc2b, 0, sizeof(sc2b));
580
581
sc2b.sam_type = PA_SAM_TYPE_SECURID;
582
sc2b.sam_response_prompt.data = NEXT_PASSCODE_message;
583
sc2b.sam_response_prompt.length =
584
strlen(sc2b.sam_response_prompt.data);
585
sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
586
sc2b.sam_etype = client_key.enctype;
587
if (new_pin) {
588
if ((AceGetMaxPinLen(sd_handle, &max_pin_len) == ACE_SUCCESS)
589
&& (AceGetMinPinLen(sd_handle,
590
&min_pin_len) == ACE_SUCCESS)
591
&& (AceGetAlphanumeric(sd_handle,
592
&alpha_pin) == ACE_SUCCESS)) {
593
sprintf(PIN_message,
594
"New PIN must contain %d to %d %sdigits",
595
min_pin_len, max_pin_len,
596
(alpha_pin == 0) ? "" : "alphanumeric ");
597
sc2b.sam_challenge_label.data = PIN_message;
598
sc2b.sam_challenge_label.length =
599
strlen(sc2b.sam_challenge_label.data);
600
} else {
601
sc2b.sam_challenge_label.length = 0;
602
}
603
}
604
605
tmp_data.data = (char *)&sc2b.sam_nonce;
606
tmp_data.length = sizeof(sc2b.sam_nonce);
607
if ((retval = krb5_c_random_make_octets(context, &tmp_data))) {
608
com_err("krb5kdc", retval,
609
"while making nonce for SecurID SAM_CHALLENGE_2 (%s)",
610
user);
611
goto cleanup;
612
}
613
if (new_pin)
614
sid_track_data.state = SECURID_STATE_NEW_PIN;
615
else
616
sid_track_data.state = SECURID_STATE_NEXT_CODE;
617
sid_track_data.handle = htonl(sd_handle);
618
sid_track_data.hostid = gethostid();
619
tmp_data.data = (char *)&sid_track_data;
620
tmp_data.length = sizeof(sid_track_data);
621
retval = securid_encrypt_track_data_2(context, client, &tmp_data,
622
&sc2b.sam_track_id);
623
if (retval) {
624
com_err("krb5kdc", retval,
625
"while encrypting SecurID track "
626
"data for SAM_CHALLENGE_2 (%s)",
627
securid_user);
628
goto cleanup;
629
}
630
retval = sam_make_challenge(context, &sc2b, &client_key, sc2p);
631
if (retval) {
632
com_err("krb5kdc", retval,
633
"while making cksum for SAM_CHALLENGE_2 (%s)",
634
securid_user);
635
}
636
if (new_pin)
637
krb5_klog_syslog(LOG_INFO, "New SecurID PIN required for "
638
"user %s", securid_user);
639
else
640
krb5_klog_syslog(LOG_INFO, "Next SecurID passcode required "
641
"for user %s", securid_user);
642
*sc2_out = sc2p;
643
sc2p = NULL;
644
retval = KRB5KDC_ERR_PREAUTH_REQUIRED;
645
/*sc2_out is permitted as an output on error path*/
646
goto cleanup;
647
}
648
default:
649
com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED,
650
"AceServer returns unknown error code %d "
651
"in verify_securid_data_2\n", retval);
652
retval = KRB5KDC_ERR_PREAUTH_FAILED;
653
goto cleanup;
654
}
655
} /* no track_id data */
656
657
cleanup:
658
krb5_free_keyblock_contents(context, &client_key);
659
free(scratch.data);
660
krb5_free_enc_sam_response_enc_2(context, esre2);
661
free(user);
662
free(securid_user);
663
free(trackp);
664
krb5_free_sam_challenge_2(context, sc2p);
665
return retval;
666
}
667
668
#endif /* ARL_SECURID_PREAUTH */
669
670