+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * plugins/preauth/securid_sam2/securid2.c
+ *
+ * Copyright (C) 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
#include "k5-int.h"
#include <kdb.h>
#include <stdio.h>
#include <adm_proto.h>
-
-
#include <syslog.h>
#include <acexport.h>
#include <sdi_defs.h>
#include <sdi_athd.h>
#include "extern.h"
-#define KRB5_SAM_SECURID_NEXT_CHALLENGE_MAGIC 0x5ec1d000
+#define KRB5_SAM_SECURID_NEXT_CHALLENGE_MAGIC 0x5ec1d000
struct securid_track_data {
- SDI_HANDLE handle;
- char state;
- char passcode[LENPRNST+1];
- long hostid;
+ SDI_HANDLE handle;
+ char state;
+ char passcode[LENPRNST+1];
+ long hostid;
};
#define SECURID_STATE_NEW_PIN 1 /* Ask for a new pin */
#define SECURID_STATE_NEXT_CODE 3 /* Ask for the next pin code */
#define SECURID_STATE_INITIAL 4
-
-static char *PASSCODE_message = "SecurID Passcode";
-static char *NEXT_PASSCODE_message = "Next Passcode";
-static char *NEW_PIN_AGAIN_message = "New PIN Again";
-static char PIN_message[64]; /* Max length should be 50 chars */
-
-/* krb5_error_code get_securid_key():
- * inputs: context: from KDC process
- * client: database entry of client executing
- * SecurID SAM preauthentication
- * outputs: client_securid_key: pointer to krb5_keyblock
- * which is key for the client's SecurID
- * database entry.
- * returns: 0 on success
- * KRB5 error codes otherwise
+static char *PASSCODE_message = "SecurID Passcode";
+static char *NEXT_PASSCODE_message = "Next Passcode";
+static char *NEW_PIN_AGAIN_message = "New PIN Again";
+static char PIN_message[64]; /* Max length should be 50 chars */
+
+/*
+ * krb5_error_code get_securid_key():
+ * inputs: context: from KDC process
+ * client: database entry of client executing
+ * SecurID SAM preauthentication
+ * outputs: client_securid_key: pointer to krb5_keyblock
+ * which is key for the client's SecurID
+ * database entry.
+ * returns: 0 on success
+ * KRB5 error codes otherwise
*
- * builds pricipal name with final instance of "SECURID" and
- * finds the database entry, decrypts the key out of the database
- * and passes the key back to the calling process
+ * builds pricipal name with final instance of "SECURID" and
+ * finds the database entry, decrypts the key out of the database
+ * and passes the key back to the calling process
*/
-static krb5_error_code get_securid_key(krb5_context context,
- krb5_db_entry *client,
- krb5_keyblock *client_securid_key)
+static krb5_error_code
+get_securid_key(krb5_context context, krb5_db_entry *client,
+ krb5_keyblock *client_securid_key)
{
- krb5_db_entry *sam_securid_entry = NULL;
+ krb5_db_entry *sam_securid_entry = NULL;
krb5_key_data *client_securid_key_data = NULL;
int sam_type = PA_SAM_TYPE_SECURID;
krb5_error_code retval = 0;
- if (!client_securid_key) return(KRB5_PREAUTH_NO_KEY);
+ if (!client_securid_key)
+ return KRB5_PREAUTH_NO_KEY;
retval = sam_get_db_entry(context, client->princ,
- &sam_type, &sam_securid_entry);
-
+ &sam_type, &sam_securid_entry);
if (retval)
- return(KRB5_PREAUTH_NO_KEY);
-
+ return KRB5_PREAUTH_NO_KEY;
- /* Find key with key_type = salt_type = kvno = -1. This finds the */
- /* latest kvno in the list. */
+ /* Find key with key_type = salt_type = kvno = -1. This finds the */
+ /* latest kvno in the list. */
retval = krb5_dbe_find_enctype(context, sam_securid_entry,
- -1, -1, -1, &client_securid_key_data);
+ -1, -1, -1, &client_securid_key_data);
if (retval) {
- krb5_set_error_message(context, retval,
- "while getting key from client's SAM SecurID entry");
- goto cleanup;
+ krb5_set_error_message(context, retval,
+ "while getting key from client's SAM SecurID "
+ "entry");
+ goto cleanup;
}
- retval = krb5_dbe_decrypt_key_data(context, NULL,
- client_securid_key_data, client_securid_key, NULL);
+ retval = krb5_dbe_decrypt_key_data(context, NULL, client_securid_key_data,
+ client_securid_key, NULL);
if (retval) {
- krb5_set_error_message(context, retval,
- "while decrypting key from client's SAM SecurID entry ");
- goto cleanup;
+ krb5_set_error_message(context, retval,
+ "while decrypting key from client's SAM "
+ "SecurID entry ");
+ goto cleanup;
}
- cleanup:
+cleanup:
if (sam_securid_entry)
- krb5_db_free_principal(context, sam_securid_entry);
+ krb5_db_free_principal(context, sam_securid_entry);
return retval;
}
krb5_error_code
-securid_make_sam_challenge_2_and_cksum (krb5_context context,
- krb5_sam_challenge_2 *sc2, krb5_sam_challenge_2_body *sc2b,
- krb5_keyblock *cksum_key)
+securid_make_sam_challenge_2_and_cksum(krb5_context context,
+ krb5_sam_challenge_2 *sc2,
+ krb5_sam_challenge_2_body *sc2b,
+ krb5_keyblock *cksum_key)
{
- krb5_error_code retval;
- krb5_checksum **cksum_array = NULL;
- krb5_checksum *cksum = NULL;
- krb5_cksumtype cksumtype;
- krb5_data *encoded_challenge_body = NULL;
-
- if (!cksum_key) return(KRB5_PREAUTH_NO_KEY);
- if (!sc2 || !sc2b) return(KRB5KDC_ERR_PREAUTH_FAILED);
-
- retval = encode_krb5_sam_challenge_2_body(sc2b, &encoded_challenge_body);
- if (retval || !encoded_challenge_body) {
- encoded_challenge_body = NULL;
- goto cksum_cleanup;
- }
-
- cksum_array = calloc(2, sizeof(krb5_checksum *));
- if (!cksum_array) {
- retval = ENOMEM;
- goto cksum_cleanup;
- }
-
- cksum = (krb5_checksum *)k5alloc(sizeof(krb5_checksum), &retval);
- if (retval)
- goto cksum_cleanup;
- cksum_array[0] = cksum;
- cksum_array[1] = NULL;
-
- retval = krb5int_c_mandatory_cksumtype(context, cksum_key->enctype, &cksumtype);
- if (retval) goto cksum_cleanup;
-
- retval = krb5_c_make_checksum(context, cksumtype,
- cksum_key, KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM,
- encoded_challenge_body, cksum);
- if (retval) goto cksum_cleanup;
-
- sc2->sam_cksum = cksum_array;
- sc2->sam_challenge_2_body = *encoded_challenge_body;
- return(0);
+ krb5_error_code retval;
+ krb5_checksum **cksum_array = NULL;
+ krb5_checksum *cksum = NULL;
+ krb5_cksumtype cksumtype;
+ krb5_data *encoded_challenge_body = NULL;
+
+ if (!cksum_key)
+ return KRB5_PREAUTH_NO_KEY;
+ if (!sc2 || !sc2b)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+
+ retval = encode_krb5_sam_challenge_2_body(sc2b, &encoded_challenge_body);
+ if (retval || !encoded_challenge_body) {
+ encoded_challenge_body = NULL;
+ goto cksum_cleanup;
+ }
+
+ cksum_array = calloc(2, sizeof(krb5_checksum *));
+ if (!cksum_array) {
+ retval = ENOMEM;
+ goto cksum_cleanup;
+ }
+
+ cksum = (krb5_checksum *)k5alloc(sizeof(krb5_checksum), &retval);
+ if (retval)
+ goto cksum_cleanup;
+ cksum_array[0] = cksum;
+ cksum_array[1] = NULL;
+
+ retval = krb5int_c_mandatory_cksumtype(context, cksum_key->enctype,
+ &cksumtype);
+ if (retval)
+ goto cksum_cleanup;
+
+ retval = krb5_c_make_checksum(context, cksumtype, cksum_key,
+ KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM,
+ encoded_challenge_body, cksum);
+ if (retval)
+ goto cksum_cleanup;
+
+ sc2->sam_cksum = cksum_array;
+ sc2->sam_challenge_2_body = *encoded_challenge_body;
+ return 0;
cksum_cleanup:
- if (encoded_challenge_body) krb5_free_data(context, encoded_challenge_body);
- if (cksum_array) krb5_xfree(cksum_array);
- if (cksum) krb5_xfree(cksum);
- return (retval);
+ krb5_free_data(context, encoded_challenge_body);
+ free(cksum_array);
+ free(cksum);
+ return retval;
}
static krb5_error_code
securid_decrypt_track_data_2(krb5_context context, krb5_db_entry *client,
- krb5_data *enc_track_data, krb5_data *output) {
+ krb5_data *enc_track_data, krb5_data *output)
+{
krb5_error_code retval;
krb5_keyblock sam_key;
krb5_enc_data tmp_enc_data;
sam_key.contents = NULL;
- if ((retval = get_securid_key(context, client,
- &sam_key) ) != 0)
- return(retval);
+ retval = get_securid_key(context, client, &sam_key);
+ if (retval != 0)
+ return retval;
tmp_enc_data.ciphertext = *enc_track_data;
tmp_enc_data.enctype = ENCTYPE_UNKNOWN;
tmp_enc_data.kvno = 0;
output->length = tmp_enc_data.ciphertext.length;
- if (output->data)
- free(output->data);
+ free(output->data);
output->data = k5alloc(output->length, &retval);
- if (retval) goto cleanup;
+ if (output->data == NULL)
+ goto cleanup;
retval = krb5_c_decrypt(context, &sam_key,
- KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0, &tmp_enc_data, output);
- cleanup:
+ KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0,
+ &tmp_enc_data, output);
+cleanup:
krb5_free_keyblock_contents(context, &sam_key);
if (retval) {
- output->length = 0;
- if (output->data)
- free(output->data);
- output->data = NULL;
- return(retval);
+ output->length = 0;
+ free(output->data);
+ output->data = NULL;
+ return retval;
}
- return(0);
+ return 0;
}
static krb5_error_code
securid_encrypt_track_data_2(krb5_context context, krb5_db_entry *client,
- krb5_data *track_data, krb5_data *output) {
+ krb5_data *track_data, krb5_data *output)
+{
krb5_error_code retval;
size_t olen;
krb5_keyblock sam_key;
krb5_enc_data tmp_enc_data;
+
output->data = NULL;
- if ((retval = get_securid_key(context,client,
- &sam_key)) != 0)
- return(retval);
+ retval = get_securid_key(context,client, &sam_key);
+ if (retval != 0)
+ return retval;
- if ((retval = krb5_c_encrypt_length(context, sam_key.enctype,
- track_data->length, &olen)) != 0)
- goto cleanup;
- assert (olen <= 65536);
+ retval = krb5_c_encrypt_length(context, sam_key.enctype,
+ track_data->length, &olen);
+ if (retval != 0)
+ goto cleanup;
+ assert(olen <= 65536);
output->length = olen;
output->data = k5alloc(output->length, &retval);
if (retval)
- goto cleanup;
+ goto cleanup;
tmp_enc_data.ciphertext = *output;
tmp_enc_data.enctype = sam_key.enctype;
tmp_enc_data.kvno = 0;
retval = krb5_c_encrypt(context, &sam_key,
- KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0, track_data, &tmp_enc_data);
- cleanup:
+ KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0,
+ track_data, &tmp_enc_data);
+cleanup:
krb5_free_keyblock_contents(context, &sam_key);
if (retval) {
- output->length = 0;
- if (output->data)
- krb5_xfree(output->data);
- output->data = NULL;
- return(retval);
+ output->length = 0;
+ free(output->data);
+ output->data = NULL;
+ return retval;
}
- return(0);
+ return 0;
}
-krb5_error_code get_securid_edata_2(krb5_context context,
- krb5_db_entry *client,
- krb5_sam_challenge_2_body *sc2b,
- krb5_sam_challenge_2 *sc2)
+krb5_error_code
+get_securid_edata_2(krb5_context context, krb5_db_entry *client,
+ krb5_sam_challenge_2_body *sc2b, krb5_sam_challenge_2 *sc2)
{
- krb5_error_code retval;
- krb5_data scratch;
- krb5_keyblock client_key;
- char *user = NULL;
- char *def_user = "<unknown user>";
- struct securid_track_data sid_track_data;
- krb5_data tmp_data;
- client_key.contents = NULL;
- scratch.data = NULL;
- sc2b->sam_track_id.data = NULL;
-
- retval = krb5_unparse_name(context, client->princ, &user);
- if (retval)
- goto cleanup;
-
-
- sc2b->sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
- sc2b->sam_type_name.length = 0;
- sc2b->sam_challenge_label.length = 0;
- sc2b->sam_challenge.length = 0;
- sc2b->sam_response_prompt.data = PASSCODE_message;
- sc2b->sam_response_prompt.length =
- strlen(sc2b->sam_response_prompt.data);
- sc2b->sam_pk_for_sad.length = 0;
-
- sid_track_data.state = SECURID_STATE_INITIAL;
- sid_track_data.hostid = gethostid();
- tmp_data.data = (char *) &sid_track_data;
- tmp_data.length = sizeof(sid_track_data);
- if((retval = securid_encrypt_track_data_2(context, client,
- &tmp_data,
- &sc2b->sam_track_id)) != 0) {
- krb5_set_error_message(context, retval, "While encrypting nonce track data");
- goto cleanup;
- }
-
-
- scratch.data = (char *)&sc2b->sam_nonce;
- scratch.length = sizeof(sc2b->sam_nonce);
- retval = krb5_c_random_make_octets(context, &scratch);
- if (retval) {
- krb5_set_error_message(context, retval,
- "while generating nonce data in get_securid_edata_2 (%s)",
- user ? user : def_user);
- goto cleanup;
- }
-
- /* Get the client's key */
- if ((retval = get_securid_key(context, client, &client_key)) != 0) {
- krb5_set_error_message(context, retval,
- "while getting SecurID SAM key in get_securid_edata_2 (%s)",
- user ? user : def_user);
- goto cleanup;
- }
- sc2b->sam_etype = client_key.enctype;
-
- retval = securid_make_sam_challenge_2_and_cksum(context,
- sc2, sc2b, &client_key);
- if (retval) {
- krb5_set_error_message(context, retval,
- "while making SAM_CHALLENGE_2 checksum (%s)",
- user ? user : def_user);
- }
-
- cleanup:
- krb5_free_keyblock_contents(context, &client_key);
- if (user) krb5_xfree(user);
- if (retval) {
- krb5_free_data_contents(context, &sc2b->sam_track_id);
- sc2b->sam_track_id.data = NULL;
- }
- return(retval);
+ krb5_error_code retval;
+ krb5_data scratch;
+ krb5_keyblock client_key;
+ char *user = NULL;
+ char *def_user = "<unknown user>";
+ struct securid_track_data sid_track_data;
+ krb5_data tmp_data;
+
+ client_key.contents = NULL;
+ scratch.data = NULL;
+ sc2b->sam_track_id.data = NULL;
+
+ retval = krb5_unparse_name(context, client->princ, &user);
+ if (retval)
+ goto cleanup;
+
+ sc2b->sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
+ sc2b->sam_type_name.length = 0;
+ sc2b->sam_challenge_label.length = 0;
+ sc2b->sam_challenge.length = 0;
+ sc2b->sam_response_prompt.data = PASSCODE_message;
+ sc2b->sam_response_prompt.length = strlen(sc2b->sam_response_prompt.data);
+ sc2b->sam_pk_for_sad.length = 0;
+
+ sid_track_data.state = SECURID_STATE_INITIAL;
+ sid_track_data.hostid = gethostid();
+ tmp_data.data = (char *)&sid_track_data;
+ tmp_data.length = sizeof(sid_track_data);
+ retval = securid_encrypt_track_data_2(context, client, &tmp_data,
+ &sc2b->sam_track_id);
+ if (retval != 0) {
+ krb5_set_error_message(context, retval,
+ "While encrypting nonce track data");
+ goto cleanup;
+ }
+
+ scratch.data = (char *)&sc2b->sam_nonce;
+ scratch.length = sizeof(sc2b->sam_nonce);
+ retval = krb5_c_random_make_octets(context, &scratch);
+ if (retval) {
+ krb5_set_error_message(context, retval,
+ "while generating nonce data in "
+ "get_securid_edata_2 (%s)",
+ user ? user : def_user);
+ goto cleanup;
+ }
+
+ /* Get the client's key */
+ if ((retval = get_securid_key(context, client, &client_key)) != 0) {
+ krb5_set_error_message(context, retval,
+ "while getting SecurID SAM key in "
+ "get_securid_edata_2 (%s)",
+ user ? user : def_user);
+ goto cleanup;
+ }
+ sc2b->sam_etype = client_key.enctype;
+
+ retval = securid_make_sam_challenge_2_and_cksum(context,
+ sc2, sc2b, &client_key);
+ if (retval) {
+ krb5_set_error_message(context, retval,
+ "while making SAM_CHALLENGE_2 checksum (%s)",
+ user ? user : def_user);
+ }
+
+cleanup:
+ krb5_free_keyblock_contents(context, &client_key);
+ free(user);
+ if (retval) {
+ krb5_free_data_contents(context, &sc2b->sam_track_id);
+ sc2b->sam_track_id.data = NULL;
+ }
+ return retval;
}
-krb5_error_code verify_securid_data_2(krb5_context context,
- krb5_db_entry *client,
- krb5_sam_response_2 *sr2,
- krb5_enc_tkt_part *enc_tkt_reply,
- krb5_pa_data *pa,
- krb5_sam_challenge_2 **sc2_out)
+krb5_error_code
+verify_securid_data_2(krb5_context context, krb5_db_entry *client,
+ krb5_sam_response_2 *sr2,
+ krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa,
+ krb5_sam_challenge_2 **sc2_out)
{
krb5_error_code retval;
int new_pin = 0;
memset(&scratch, 0, sizeof(scratch));
*sc2_out = NULL;
- if ((retval = krb5_unparse_name(context, client->princ, &user)) !=0 ) {
- krb5_set_error_message(context, retval,
- "while unparsing client name in verify_securid_data_2");
- return(retval);
+ retval = krb5_unparse_name(context, client->princ, &user);
+ if (retval != 0) {
+ krb5_set_error_message(context, retval,
+ "while unparsing client name in "
+ "verify_securid_data_2");
+ return retval;
}
if ((sr2->sam_enc_nonce_or_sad.ciphertext.data == NULL) ||
- (sr2->sam_enc_nonce_or_sad.ciphertext.length <= 0)) {
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- krb5_set_error_message(context, retval,
- "No preauth data supplied in verify_securid_data_2 (%s)", user);
- goto cleanup;
+ (sr2->sam_enc_nonce_or_sad.ciphertext.length <= 0)) {
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval,
+ "No preauth data supplied in "
+ "verify_securid_data_2 (%s)", user);
+ goto cleanup;
}
retval = krb5_dbe_find_enctype(context, client,
- sr2->sam_enc_nonce_or_sad.enctype, KRB5_KDB_SALTTYPE_NORMAL,
- sr2->sam_enc_nonce_or_sad.kvno , &client_key_data);
+ sr2->sam_enc_nonce_or_sad.enctype,
+ KRB5_KDB_SALTTYPE_NORMAL,
+ sr2->sam_enc_nonce_or_sad.kvno,
+ &client_key_data);
if (retval) {
- krb5_set_error_message(context, retval,
- "while getting client key in verify_securid_data_2 (%s)", user);
- goto cleanup;
+ krb5_set_error_message(context, retval,
+ "while getting client key in "
+ "verify_securid_data_2 (%s)", user);
+ goto cleanup;
}
- if ((retval = krb5_dbe_decrypt_key_data(context, NULL,
- client_key_data, &client_key, NULL)) != 0) {
- krb5_set_error_message(context, retval,
- "while decrypting client key in verify_securid_data_2 (%s)",
- user);
- goto cleanup;
+ retval = krb5_dbe_decrypt_key_data(context, NULL, client_key_data,
+ &client_key, NULL);
+ if (retval != 0) {
+ krb5_set_error_message(context, retval,
+ "while decrypting client key in "
+ "verify_securid_data_2 (%s)",
+ user);
+ goto cleanup;
}
scratch.length = sr2->sam_enc_nonce_or_sad.ciphertext.length;
scratch.data = k5alloc(scratch.length, &retval);
if (retval)
- goto cleanup;
+ goto cleanup;
retval = krb5_c_decrypt(context, &client_key,
- KRB5_KEYUSAGE_PA_SAM_RESPONSE, 0,
- &sr2->sam_enc_nonce_or_sad, &scratch);
+ KRB5_KEYUSAGE_PA_SAM_RESPONSE, 0,
+ &sr2->sam_enc_nonce_or_sad, &scratch);
if (retval) {
- krb5_set_error_message(context, retval,
- "while decrypting SAD in verify_securid_data_2 (%s)", user);
- goto cleanup;
+ krb5_set_error_message(context, retval,
+ "while decrypting SAD in "
+ "verify_securid_data_2 (%s)", user);
+ goto cleanup;
}
retval = decode_krb5_enc_sam_response_enc_2(&scratch, &esre2);
if (retval) {
- krb5_set_error_message(context, retval,
- "while decoding SAD in verify_securid_data_2 (%s)", user);
- esre2 = NULL;
- goto cleanup;
+ krb5_set_error_message(context, retval,
+ "while decoding SAD in "
+ "verify_securid_data_2 (%s)", user);
+ esre2 = NULL;
+ goto cleanup;
}
if (sr2->sam_nonce != esre2->sam_nonce) {
- krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
- "while checking nonce in verify_securid_data_2 (%s)", user);
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- goto cleanup;
+ krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
+ "while checking nonce in "
+ "verify_securid_data_2 (%s)", user);
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto cleanup;
}
- if ((esre2->sam_sad.length == 0) || (esre2->sam_sad.data == NULL)) {
- krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
- "No SecurID passcode in verify_securid_data_2 (%s)", user);
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- goto cleanup;
+ if (esre2->sam_sad.length == 0 || esre2->sam_sad.data == NULL) {
+ krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
+ "No SecurID passcode in "
+ "verify_securid_data_2 (%s)", user);
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto cleanup;
}
/* Copy out SAD to null-terminated buffer */
memset(passcode, 0, sizeof(passcode));
if (esre2->sam_sad.length > (sizeof(passcode) - 1)) {
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- krb5_set_error_message(context, retval,
- "SecurID passcode/PIN too long (%d bytes) in verify_securid_data_2 (%s)",
- esre2->sam_sad.length, user);
- goto cleanup;
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval,
+ "SecurID passcode/PIN too long (%d bytes) in "
+ "verify_securid_data_2 (%s)",
+ esre2->sam_sad.length, user);
+ goto cleanup;
}
memcpy(passcode, esre2->sam_sad.data, esre2->sam_sad.length);
securid_user = strdup(user);
if (!securid_user) {
- retval = ENOMEM;
- krb5_set_error_message(context, ENOMEM,
- "while copying user name in verify_securid_data_2 (%s)", user);
- goto cleanup;
+ retval = ENOMEM;
+ krb5_set_error_message(context, ENOMEM,
+ "while copying user name in "
+ "verify_securid_data_2 (%s)", user);
+ goto cleanup;
}
- if ((cp = strchr(securid_user, '@')))
- *cp = (char)0;
+ cp = strchr(securid_user, '@');
+ if (cp != NULL)
+ *cp = '\0';
- /* Check for any track_id data that may have state from a previous */
- /* attempt at SecurID authentication */
+ /* Check for any track_id data that may have state from a previous attempt
+ * at SecurID authentication. */
if (sr2->sam_track_id.data && (sr2->sam_track_id.length > 0)) {
- krb5_data track_id_data;
- memset(&track_id_data, 0, sizeof(track_id_data));
- retval = securid_decrypt_track_data_2(context, client,
- &sr2->sam_track_id, &track_id_data);
- if (retval) {
- krb5_set_error_message(context, retval,
- "while decrypting SecurID trackID in verify_securid_data_2 (%s)",
- user);
- goto cleanup;
- }
- if (track_id_data.length <= sizeof (struct securid_track_data)) {
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- krb5_set_error_message(context, retval, "Length of track data incorrect");
- goto cleanup;
- }
- trackp = (struct securid_track_data *)track_id_data.data;
-
- if(trackp->hostid != gethostid()) {
- krb5_klog_syslog(LOG_INFO, "Unexpected challenge response");
- retval = KRB5KDC_ERR_DISCARD;
- goto cleanup;
- }
-
- switch(trackp->state) {
- case SECURID_STATE_INITIAL:
- goto initial;
- break;
- case SECURID_STATE_NEW_PIN_AGAIN:
- {
- int pin1_len, pin2_len;
-
- trackp->handle = ntohl(trackp->handle);
- pin2_len = strlen(passcode);
- pin1_len = strlen(trackp->passcode);
-
- if ((pin1_len != pin2_len) ||
- (memcmp(passcode, trackp->passcode, pin1_len) != 0)) {
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- krb5_klog_syslog(LOG_INFO,
- "New SecurID PIN Failed for user %s: PIN mis-match",
- user);
- break;
- }
- retval = SD_Pin(trackp->handle, passcode);
- SD_Close(trackp->handle);
- if (retval == ACM_NEW_PIN_ACCEPTED) {
- enc_tkt_reply->flags|= TKT_FLG_HW_AUTH;
- enc_tkt_reply->flags|= TKT_FLG_PRE_AUTH;
- krb5_klog_syslog(LOG_INFO,
- "SecurID PIN Accepted for %s in verify_securid_data_2",
- securid_user);
- retval = 0;
- } else {
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- krb5_klog_syslog(LOG_INFO,
- "SecurID PIN Failed for user %s (AceServer returns %d) in verify_securid_data_2",
- user, retval);
- }
- break;
- }
- case SECURID_STATE_NEW_PIN: {
- krb5_sam_challenge_2_body sc2b;
- sc2p = k5alloc(sizeof *sc2p, &retval);
- if (retval)
- goto cleanup;
- memset(sc2p, 0, sizeof(*sc2p));
- memset(&sc2b, 0, sizeof(sc2b));
- sc2b.sam_type = PA_SAM_TYPE_SECURID;
- sc2b.sam_response_prompt.data = NEW_PIN_AGAIN_message;
- sc2b.sam_response_prompt.length =
- strlen(sc2b.sam_response_prompt.data);
- sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
- sc2b.sam_etype = client_key.enctype;
-
- tmp_data.data = (char *)&sc2b.sam_nonce;
- tmp_data.length = sizeof(sc2b.sam_nonce);
- if ((retval = krb5_c_random_make_octets(context, &tmp_data))) {
- krb5_set_error_message(context, retval,
- "while making nonce for SecurID new PIN2 SAM_CHALLENGE_2 (%s)", user);
- goto cleanup;
- }
- sid_track_data.state = SECURID_STATE_NEW_PIN_AGAIN;
- sid_track_data.handle = trackp->handle;
- sid_track_data.hostid = gethostid();
- /* Should we complain if sizes don't work ?? */
- memcpy(sid_track_data.passcode, passcode,
- sizeof(sid_track_data.passcode));
- tmp_data.data = (char *)&sid_track_data;
- tmp_data.length = sizeof(sid_track_data);
- if ((retval = securid_encrypt_track_data_2(context, client,
- &tmp_data, &sc2b.sam_track_id))) {
- krb5_set_error_message(context, retval,
- "while encrypting NEW PIN2 SecurID track data for SAM_CHALLENGE_2 (%s)",
- securid_user);
- goto cleanup;
- }
- retval = securid_make_sam_challenge_2_and_cksum(context, sc2p,
- &sc2b, &client_key);
- if (retval) {
- krb5_set_error_message(context, retval,
- "while making cksum for SAM_CHALLENGE_2 (new PIN2) (%s)",
- securid_user);
- goto cleanup;
- }
- krb5_klog_syslog(LOG_INFO,
- "Requesting verification of new PIN for user %s",
- securid_user);
- *sc2_out = sc2p;
- sc2p = NULL;
- /*sc2_out may be set even on error path*/
- retval = KRB5KDC_ERR_PREAUTH_REQUIRED;
- goto cleanup;
- }
- case SECURID_STATE_NEXT_CODE:
- trackp->handle = ntohl(trackp->handle);
- retval = SD_Next(trackp->handle, passcode);
- SD_Close(trackp->handle);
- if (retval == ACM_OK) {
- enc_tkt_reply->flags |= TKT_FLG_HW_AUTH
- | TKT_FLG_PRE_AUTH;
-
- krb5_klog_syslog(LOG_INFO,
- "Next SecurID Code Accepted for user %s", securid_user);
- retval = 0;
- } else {
- krb5_klog_syslog(LOG_INFO,
- "Next SecurID Code Failed for user %s (AceServer returns %d) in verify_securid_data_2",
- user, retval);
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- }
- break;
- }
- } else { /* No track data, this is first of N attempts */
-initial:
- if ((retval = SD_Init(&sd_handle))) {
- krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
- "SD_Init() returns error %d in verify_securid_data_2 (%s)",
- retval, securid_user);
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- goto cleanup;
- }
-
- if((retval = SD_Lock(sd_handle, securid_user)) != ACM_OK) {
- SD_Close(sd_handle);
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- krb5_klog_syslog(LOG_INFO,
- "SD_Lock() failed (AceServer returns %d) for %s",
- retval, securid_user);
- goto cleanup;
- }
-
- retval = SD_Check(sd_handle, passcode, securid_user);
- switch (retval) {
- case ACM_OK:
- SD_Close(sd_handle);
- enc_tkt_reply->flags|= TKT_FLG_HW_AUTH;
- enc_tkt_reply->flags|= TKT_FLG_PRE_AUTH;
- krb5_klog_syslog(LOG_INFO,
- "SecurID passcode accepted for user %s", user);
- retval = 0;
- break;
- case ACM_ACCESS_DENIED:
- SD_Close(sd_handle);
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- krb5_klog_syslog(LOG_INFO,
- "AceServer returns Access Denied for user %s (SAM2)",user);
- goto cleanup;
- case ACM_NEW_PIN_REQUIRED:
- new_pin = 1;
- /*fall through*/
- case ACM_NEXT_CODE_REQUIRED: {
- krb5_sam_challenge_2_body sc2b;
- sc2p = k5alloc(sizeof *sc2p, &retval);
- if (retval)
- goto cleanup;
-
- memset(sc2p, 0, sizeof(*sc2p));
- memset(&sc2b, 0, sizeof(sc2b));
-
- sc2b.sam_type = PA_SAM_TYPE_SECURID;
- sc2b.sam_response_prompt.data = NEXT_PASSCODE_message;
- sc2b.sam_response_prompt.length =
- strlen(sc2b.sam_response_prompt.data);
- sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
- sc2b.sam_etype = client_key.enctype;
- if (new_pin) {
- if ((AceGetMaxPinLen(sd_handle, &max_pin_len) == ACE_SUCCESS)
- && (AceGetMinPinLen(sd_handle, &min_pin_len) == ACE_SUCCESS)
- && (AceGetAlphanumeric(sd_handle, &alpha_pin) == ACE_SUCCESS))
- {
- sprintf(PIN_message,
- "New PIN must contain %d to %d %sdigits",
- min_pin_len, max_pin_len,
- (alpha_pin == 0) ? "" : "alphanumeric ");
- sc2b.sam_challenge_label.data = PIN_message;
- sc2b.sam_challenge_label.length =
- strlen(sc2b.sam_challenge_label.data);
- } else {
- sc2b.sam_challenge_label.length = 0;
- }
- }
-
- tmp_data.data = (char *)&sc2b.sam_nonce;
- tmp_data.length = sizeof(sc2b.sam_nonce);
- if ((retval = krb5_c_random_make_octets(context, &tmp_data))) {
- krb5_set_error_message(context, retval,
- "while making nonce for SecurID SAM_CHALLENGE_2 (%s)", user);
- goto cleanup;
- }
- if (new_pin)
- sid_track_data.state = SECURID_STATE_NEW_PIN;
- else sid_track_data.state = SECURID_STATE_NEXT_CODE;
- sid_track_data.handle = htonl(sd_handle);
- sid_track_data.hostid = gethostid();
- tmp_data.data = (char *)&sid_track_data;
- tmp_data.length = sizeof(sid_track_data);
- if ((retval = securid_encrypt_track_data_2(context, client,
- &tmp_data, &sc2b.sam_track_id))) {
- krb5_set_error_message(context, retval,
- "while encrypting SecurID track data for SAM_CHALLENGE_2 (%s)",
- securid_user);
- goto cleanup;
- }
- retval = securid_make_sam_challenge_2_and_cksum(context, sc2p,
- &sc2b, &client_key);
- if (retval) {
- krb5_set_error_message(context, retval,
- "while making cksum for SAM_CHALLENGE_2 (%s)",
- securid_user);
- }
- if (new_pin)
- krb5_klog_syslog(LOG_INFO,
- "New SecurID PIN required for user %s", securid_user);
- else krb5_klog_syslog(LOG_INFO,
- "Next SecurID passcode required for user %s", securid_user);
- *sc2_out = sc2p;
- sc2p = NULL;
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- /*sc2_out is permitted as an output on error path*/
- goto cleanup;
- }
- default:
- krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
- "AceServer returns unknown error code %d in verify_securid_data_2\n", retval);
- retval = KRB5KDC_ERR_PREAUTH_FAILED;
- goto cleanup;
- }
- } /* no track_id data */
+ krb5_data track_id_data;
+
+ memset(&track_id_data, 0, sizeof(track_id_data));
+ retval = securid_decrypt_track_data_2(context, client,
+ &sr2->sam_track_id,
+ &track_id_data);
+ if (retval) {
+ krb5_set_error_message(context, retval,
+ "while decrypting SecurID trackID in "
+ "verify_securid_data_2 (%s)", user);
+ goto cleanup;
+ }
+ if (track_id_data.length <= sizeof (struct securid_track_data)) {
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval,
+ "Length of track data incorrect");
+ goto cleanup;
+ }
+ trackp = (struct securid_track_data *)track_id_data.data;
+
+ if(trackp->hostid != gethostid()) {
+ krb5_klog_syslog(LOG_INFO, "Unexpected challenge response");
+ retval = KRB5KDC_ERR_DISCARD;
+ goto cleanup;
+ }
+
+ switch(trackp->state) {
+ case SECURID_STATE_INITIAL:
+ goto initial;
+ break;
+ case SECURID_STATE_NEW_PIN_AGAIN:
+ {
+ int pin1_len, pin2_len;
+
+ trackp->handle = ntohl(trackp->handle);
+ pin2_len = strlen(passcode);
+ pin1_len = strlen(trackp->passcode);
+
+ if ((pin1_len != pin2_len) ||
+ (memcmp(passcode, trackp->passcode, pin1_len) != 0)) {
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_klog_syslog(LOG_INFO, "New SecurID PIN Failed for user "
+ "%s: PIN mis-match", user);
+ break;
+ }
+ retval = SD_Pin(trackp->handle, passcode);
+ SD_Close(trackp->handle);
+ if (retval == ACM_NEW_PIN_ACCEPTED) {
+ enc_tkt_reply->flags|= TKT_FLG_HW_AUTH;
+ enc_tkt_reply->flags|= TKT_FLG_PRE_AUTH;
+ krb5_klog_syslog(LOG_INFO, "SecurID PIN Accepted for %s in "
+ "verify_securid_data_2",
+ securid_user);
+ retval = 0;
+ } else {
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_klog_syslog(LOG_INFO,
+ "SecurID PIN Failed for user %s (AceServer "
+ "returns %d) in verify_securid_data_2",
+ user, retval);
+ }
+ break;
+ }
+ case SECURID_STATE_NEW_PIN: {
+ krb5_sam_challenge_2_body sc2b;
+ sc2p = k5alloc(sizeof *sc2p, &retval);
+ if (retval)
+ goto cleanup;
+ memset(sc2p, 0, sizeof(*sc2p));
+ memset(&sc2b, 0, sizeof(sc2b));
+ sc2b.sam_type = PA_SAM_TYPE_SECURID;
+ sc2b.sam_response_prompt.data = NEW_PIN_AGAIN_message;
+ sc2b.sam_response_prompt.length =
+ strlen(sc2b.sam_response_prompt.data);
+ sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
+ sc2b.sam_etype = client_key.enctype;
+
+ tmp_data.data = (char *)&sc2b.sam_nonce;
+ tmp_data.length = sizeof(sc2b.sam_nonce);
+ if ((retval = krb5_c_random_make_octets(context, &tmp_data))) {
+ krb5_set_error_message(context, retval,
+ "while making nonce for SecurID new "
+ "PIN2 SAM_CHALLENGE_2 (%s)", user);
+ goto cleanup;
+ }
+ sid_track_data.state = SECURID_STATE_NEW_PIN_AGAIN;
+ sid_track_data.handle = trackp->handle;
+ sid_track_data.hostid = gethostid();
+ /* Should we complain if sizes don't work ?? */
+ memcpy(sid_track_data.passcode, passcode,
+ sizeof(sid_track_data.passcode));
+ tmp_data.data = (char *)&sid_track_data;
+ tmp_data.length = sizeof(sid_track_data);
+ if ((retval = securid_encrypt_track_data_2(context, client,
+ &tmp_data,
+ &sc2b.sam_track_id))) {
+ krb5_set_error_message(context, retval,
+ "while encrypting NEW PIN2 SecurID "
+ "track data for SAM_CHALLENGE_2 (%s)",
+ securid_user);
+ goto cleanup;
+ }
+ retval = securid_make_sam_challenge_2_and_cksum(context, sc2p,
+ &sc2b,
+ &client_key);
+ if (retval) {
+ krb5_set_error_message(context, retval,
+ "while making cksum for "
+ "SAM_CHALLENGE_2 (new PIN2) (%s)",
+ securid_user);
+ goto cleanup;
+ }
+ krb5_klog_syslog(LOG_INFO,
+ "Requesting verification of new PIN for user %s",
+ securid_user);
+ *sc2_out = sc2p;
+ sc2p = NULL;
+ /*sc2_out may be set even on error path*/
+ retval = KRB5KDC_ERR_PREAUTH_REQUIRED;
+ goto cleanup;
+ }
+ case SECURID_STATE_NEXT_CODE:
+ trackp->handle = ntohl(trackp->handle);
+ retval = SD_Next(trackp->handle, passcode);
+ SD_Close(trackp->handle);
+ if (retval == ACM_OK) {
+ enc_tkt_reply->flags |= TKT_FLG_HW_AUTH | TKT_FLG_PRE_AUTH;
+
+ krb5_klog_syslog(LOG_INFO, "Next SecurID Code Accepted for "
+ "user %s", securid_user);
+ retval = 0;
+ } else {
+ krb5_klog_syslog(LOG_INFO, "Next SecurID Code Failed for user "
+ "%s (AceServer returns %d) in "
+ "verify_securid_data_2", user, retval);
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ break;
+ }
+ } else { /* No track data, this is first of N attempts */
+ initial:
+ retval = SD_Init(&sd_handle);
+ if (retval) {
+ krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
+ "SD_Init() returns error %d in "
+ "verify_securid_data_2 (%s)",
+ retval, securid_user);
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto cleanup;
+ }
+
+ retval = SD_Lock(sd_handle, securid_user);
+ if (retval != ACM_OK) {
+ SD_Close(sd_handle);
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_klog_syslog(LOG_INFO,
+ "SD_Lock() failed (AceServer returns %d) for %s",
+ retval, securid_user);
+ goto cleanup;
+ }
+
+ retval = SD_Check(sd_handle, passcode, securid_user);
+ switch (retval) {
+ case ACM_OK:
+ SD_Close(sd_handle);
+ enc_tkt_reply->flags|= TKT_FLG_HW_AUTH;
+ enc_tkt_reply->flags|= TKT_FLG_PRE_AUTH;
+ krb5_klog_syslog(LOG_INFO, "SecurID passcode accepted for user %s",
+ user);
+ retval = 0;
+ break;
+ case ACM_ACCESS_DENIED:
+ SD_Close(sd_handle);
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_klog_syslog(LOG_INFO, "AceServer returns Access Denied for "
+ "user %s (SAM2)", user);
+ goto cleanup;
+ case ACM_NEW_PIN_REQUIRED:
+ new_pin = 1;
+ /*fall through*/
+ case ACM_NEXT_CODE_REQUIRED: {
+ krb5_sam_challenge_2_body sc2b;
+ sc2p = k5alloc(sizeof *sc2p, &retval);
+ if (retval)
+ goto cleanup;
+
+ memset(sc2p, 0, sizeof(*sc2p));
+ memset(&sc2b, 0, sizeof(sc2b));
+
+ sc2b.sam_type = PA_SAM_TYPE_SECURID;
+ sc2b.sam_response_prompt.data = NEXT_PASSCODE_message;
+ sc2b.sam_response_prompt.length =
+ strlen(sc2b.sam_response_prompt.data);
+ sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
+ sc2b.sam_etype = client_key.enctype;
+ if (new_pin) {
+ if ((AceGetMaxPinLen(sd_handle, &max_pin_len) == ACE_SUCCESS)
+ && (AceGetMinPinLen(sd_handle,
+ &min_pin_len) == ACE_SUCCESS)
+ && (AceGetAlphanumeric(sd_handle,
+ &alpha_pin) == ACE_SUCCESS)) {
+ sprintf(PIN_message,
+ "New PIN must contain %d to %d %sdigits",
+ min_pin_len, max_pin_len,
+ (alpha_pin == 0) ? "" : "alphanumeric ");
+ sc2b.sam_challenge_label.data = PIN_message;
+ sc2b.sam_challenge_label.length =
+ strlen(sc2b.sam_challenge_label.data);
+ } else {
+ sc2b.sam_challenge_label.length = 0;
+ }
+ }
+
+ tmp_data.data = (char *)&sc2b.sam_nonce;
+ tmp_data.length = sizeof(sc2b.sam_nonce);
+ if ((retval = krb5_c_random_make_octets(context, &tmp_data))) {
+ krb5_set_error_message(context, retval, "while making nonce "
+ "for SecurID SAM_CHALLENGE_2 (%s)",
+ user);
+ goto cleanup;
+ }
+ if (new_pin)
+ sid_track_data.state = SECURID_STATE_NEW_PIN;
+ else
+ sid_track_data.state = SECURID_STATE_NEXT_CODE;
+ sid_track_data.handle = htonl(sd_handle);
+ sid_track_data.hostid = gethostid();
+ tmp_data.data = (char *)&sid_track_data;
+ tmp_data.length = sizeof(sid_track_data);
+ retval = securid_encrypt_track_data_2(context, client, &tmp_data,
+ &sc2b.sam_track_id);
+ if (retval) {
+ krb5_set_error_message(context, retval,
+ "while encrypting SecurID track "
+ "data for SAM_CHALLENGE_2 (%s)",
+ securid_user);
+ goto cleanup;
+ }
+ retval = securid_make_sam_challenge_2_and_cksum(context, sc2p,
+ &sc2b,
+ &client_key);
+ if (retval) {
+ krb5_set_error_message(context, retval, "while making cksum "
+ "for SAM_CHALLENGE_2 (%s)",
+ securid_user);
+ }
+ if (new_pin)
+ krb5_klog_syslog(LOG_INFO, "New SecurID PIN required for "
+ "user %s", securid_user);
+ else
+ krb5_klog_syslog(LOG_INFO, "Next SecurID passcode required "
+ "for user %s", securid_user);
+ *sc2_out = sc2p;
+ sc2p = NULL;
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ /*sc2_out is permitted as an output on error path*/
+ goto cleanup;
+ }
+ default:
+ krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
+ "AceServer returns unknown error code %d "
+ "in verify_securid_data_2\n", retval);
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto cleanup;
+ }
+ } /* no track_id data */
cleanup:
- if (client_key.contents) krb5_free_keyblock_contents(context, &client_key);
- if (scratch.data) krb5_xfree(scratch.data);
- if (esre2) krb5_free_enc_sam_response_enc_2(context, esre2);
- if (user) krb5_xfree(user);
- if (securid_user) krb5_xfree(securid_user);
- if (trackp) krb5_xfree(trackp);
- if (sc2p)
- krb5_free_sam_challenge_2(context, sc2p);
- return(retval);
+ krb5_free_keyblock_contents(context, &client_key);
+ free(scratch.data);
+ krb5_free_enc_sam_response_enc_2(context, esre2);
+ free(user);
+ free(securid_user);
+ free(trackp);
+ krb5_free_sam_challenge_2(context, sc2p);
+ return retval;
}
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
- * plugins/preauth/encrypted_challenge/encrypted_challenge.c
+ * plugins/preauth/securid_sam2/securid_sam2_main.c
*
* Copyright (C) 2009, 2010 by the Massachusetts Institute of Technology.
* All rights reserved.
#include <kdb.h>
#include "extern.h"
-
static struct {
- char* name;
- int sam_type;
+ char* name;
+ int sam_type;
} *sam_ptr, sam_inst_map[] = {
- { "SECURID", PA_SAM_TYPE_SECURID, },
- { "GRAIL", PA_SAM_TYPE_GRAIL, },
- { 0, 0 },
+ { "SECURID", PA_SAM_TYPE_SECURID, },
+ { "GRAIL", PA_SAM_TYPE_GRAIL, },
+ { 0, 0 },
};
- krb5_error_code sam_get_db_entry(
- krb5_context context,
- krb5_principal client,
- int *sam_type,
- struct _krb5_db_entry_new **db_entry)
+krb5_error_code
+sam_get_db_entry(krb5_context context, krb5_principal client,
+ int *sam_type, struct _krb5_db_entry_new **db_entry)
{
struct _krb5_db_entry_new *assoc = NULL;
- krb5_principal newp = NULL;
- int probeslot;
- void *ptr = NULL;
- krb5_error_code retval;
- if (db_entry)
+ krb5_principal newp = NULL;
+ int probeslot;
+ void *ptr = NULL;
+ krb5_error_code retval;
+
+ if (db_entry)
*db_entry = NULL;
- retval = krb5_copy_principal(context, client, &newp);
- if (retval) {
- krb5_set_error_message(context, retval, "copying client name for preauth probe");
- return retval;
- }
+ retval = krb5_copy_principal(context, client, &newp);
+ if (retval) {
+ krb5_set_error_message(context, retval,
+ "copying client name for preauth probe");
+ return retval;
+ }
- probeslot = krb5_princ_size(context, newp)++;
- ptr =
- realloc(krb5_princ_name(context, newp),
- krb5_princ_size(context, newp) * sizeof(krb5_data));
+ probeslot = krb5_princ_size(context, newp)++;
+ ptr = realloc(krb5_princ_name(context, newp),
+ krb5_princ_size(context, newp) * sizeof(krb5_data));
if (ptr == NULL) {
retval = ENOMEM;
goto cleanup;
- } else krb5_princ_name(context, newp) = ptr;
+ }
+ krb5_princ_name(context, newp) = ptr;
for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) {
- if (*sam_type && (*sam_type != sam_ptr->sam_type)) continue;
+ if (*sam_type && *sam_type != sam_ptr->sam_type)
+ continue;
- krb5_princ_component(context,newp,probeslot)->data = sam_ptr->name;
- krb5_princ_component(context,newp,probeslot)->length =
- strlen(sam_ptr->name);
- retval = krb5_db_get_principal(context, newp, 0, &assoc);
- if(!retval )
- break;
- }
+ krb5_princ_component(context,newp,probeslot)->data = sam_ptr->name;
+ krb5_princ_component(context,newp,probeslot)->length =
+ strlen(sam_ptr->name);
+ retval = krb5_db_get_principal(context, newp, 0, &assoc);
+ if (!retval)
+ break;
+ }
cleanup:
if (ptr) {
krb5_princ_component(context,newp,probeslot)->data = 0;
if (retval)
return retval;
if (sam_ptr->sam_type) {
- /* Found entry of type sam_ptr->sam_type */
- if (sam_type) *sam_type = sam_ptr->sam_type;
- if (db_entry) *db_entry = assoc;
- else krb5_db_free_principal( context, assoc);
- return(0);
+ /* Found entry of type sam_ptr->sam_type */
+ if (sam_type)
+ *sam_type = sam_ptr->sam_type;
+ if (db_entry)
+ *db_entry = assoc;
+ else
+ krb5_db_free_principal(context, assoc);
+ return 0;
} else {
- return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+ return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
}
}
preauth_get_entry_data_proc get_entry_proc,
void *pa_module_context, krb5_pa_data *pa_data)
{
- krb5_error_code retval;
- krb5_sam_challenge_2 sc2;
- krb5_sam_challenge_2_body sc2b;
- int sam_type = 0; /* unknown */
- krb5_db_entry *sam_db_entry = NULL;
- krb5_data *encoded_challenge = NULL;
- memset(&sc2, 0, sizeof(sc2));
- memset(&sc2b, 0, sizeof(sc2b));
- sc2b.magic = KV5M_SAM_CHALLENGE_2;
- sc2b.sam_type = sam_type;
+ krb5_error_code retval;
+ krb5_sam_challenge_2 sc2;
+ krb5_sam_challenge_2_body sc2b;
+ int sam_type = 0; /* unknown */
+ krb5_db_entry *sam_db_entry = NULL;
+ krb5_data *encoded_challenge = NULL;
- retval = sam_get_db_entry(context, client->princ, &sam_type,
- &sam_db_entry);
- if (retval) return (retval);
+ memset(&sc2, 0, sizeof(sc2));
+ memset(&sc2b, 0, sizeof(sc2b));
+ sc2b.magic = KV5M_SAM_CHALLENGE_2;
+ sc2b.sam_type = sam_type;
- if (sam_type == 0) {
- retval = KRB5_PREAUTH_BAD_TYPE;
- goto cleanup;
- }
+ retval = sam_get_db_entry(context, client->princ, &sam_type,
+ &sam_db_entry);
+ if (retval)
+ return retval;
- /* Defer getting the key for the SAM principal associated with the */
- /* client until the mechanism-specific code. The mechanism may want */
- /* to get a specific keytype */
+ if (sam_type == 0) {
+ retval = KRB5_PREAUTH_BAD_TYPE;
+ goto cleanup;
+ }
+ /*
+ * Defer getting the key for the SAM principal associated with the client
+ * until the mechanism-specific code. The mechanism may want to get a
+ * specific keytype.
+ */
- switch (sam_type) {
+ switch (sam_type) {
#ifdef ARL_SECURID_PREAUTH
- case PA_SAM_TYPE_SECURID:
- if ((retval = get_securid_edata_2(context, client, &sc2b, &sc2)))
- goto cleanup;
+ case PA_SAM_TYPE_SECURID:
+ retval = get_securid_edata_2(context, client, &sc2b, &sc2);
+ if (retval)
+ goto cleanup;
- retval = encode_krb5_sam_challenge_2(&sc2, &encoded_challenge);
- if (retval) {
- krb5_set_error_message(context, retval,"while encoding SECURID SAM_CHALLENGE_2");
- goto cleanup;
- }
+ retval = encode_krb5_sam_challenge_2(&sc2, &encoded_challenge);
+ if (retval) {
+ krb5_set_error_message(context, retval,
+ "while encoding SECURID SAM_CHALLENGE_2");
+ goto cleanup;
+ }
- pa_data->magic = KV5M_PA_DATA;
- pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
- pa_data->contents = (krb5_octet *) encoded_challenge->data;
- pa_data->length = encoded_challenge->length;
+ pa_data->magic = KV5M_PA_DATA;
+ pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
+ pa_data->contents = (krb5_octet *) encoded_challenge->data;
+ pa_data->length = encoded_challenge->length;
encoded_challenge->data = NULL;
- retval = 0;
- break;
+ retval = 0;
+ break;
#endif /* ARL_SECURID_PREAUTH */
- default:
- retval = KRB5_PREAUTH_BAD_TYPE;
- goto cleanup;
- }
+ default:
+ retval = KRB5_PREAUTH_BAD_TYPE;
+ goto cleanup;
+ }
cleanup:
- krb5_free_data( context, encoded_challenge);
- if (sam_db_entry)
- krb5_db_free_principal(context, sam_db_entry);
- return (retval);
+ krb5_free_data(context, encoded_challenge);
+ if (sam_db_entry)
+ krb5_db_free_principal(context, sam_db_entry);
+ return retval;
}
static krb5_error_code
krb5_data **e_data, krb5_authdata ***authz_data)
{
krb5_error_code retval;
- krb5_sam_response_2 *sr2 = NULL;
- krb5_data scratch, *scratch2;
+ krb5_sam_response_2 *sr2 = NULL;
+ krb5_data scratch, *scratch2;
char *client_name = NULL;
krb5_sam_challenge_2 *out_sc2 = NULL;
- scratch.data = (char *) pa_data->contents;
- scratch.length = pa_data->length;
+ scratch.data = (char *) pa_data->contents;
+ scratch.length = pa_data->length;
- retval = krb5_unparse_name(context, client->princ, &client_name);
- if (retval)
- goto cleanup;
+ retval = krb5_unparse_name(context, client->princ, &client_name);
+ if (retval)
+ goto cleanup;
- retval = decode_krb5_sam_response_2(&scratch, &sr2);
- if (retval) {
- krb5_set_error_message(context, retval,
- "while decoding SAM_RESPONSE_2 in verify_sam_response_2");
- sr2 = NULL;
- goto cleanup;
- }
+ retval = decode_krb5_sam_response_2(&scratch, &sr2);
+ if (retval) {
+ krb5_set_error_message(context, retval, "while decoding "
+ "SAM_RESPONSE_2 in verify_sam_response_2");
+ sr2 = NULL;
+ goto cleanup;
+ }
- switch (sr2->sam_type) {
+ switch (sr2->sam_type) {
#ifdef ARL_SECURID_PREAUTH
- case PA_SAM_TYPE_SECURID:
- retval = verify_securid_data_2(context, client, sr2,
- enc_tkt_reply, pa_data, &out_sc2);
- if (retval) goto cleanup;
- break;
+ case PA_SAM_TYPE_SECURID:
+ retval = verify_securid_data_2(context, client, sr2, enc_tkt_reply,
+ pa_data, &out_sc2);
+ if (retval)
+ goto cleanup;
+ break;
#endif /* ARL_SECURID_PREAUTH */
- default:
- retval = KRB5_PREAUTH_BAD_TYPE;
- krb5_set_error_message(context , retval, "while verifying SAM 2 data");
- break;
- }
+ default:
+ retval = KRB5_PREAUTH_BAD_TYPE;
+ krb5_set_error_message(context, retval, "while verifying SAM 2 data");
+ break;
+ }
- /* It is up to the method-specific verify routine to set the ticket flags */
- /* to indicate TKT_FLG_HW_AUTH and/or TKT_FLG_PRE_AUTH. Some methods */
- /* may require more than one round of dialog with the client and must */
- /* return successfully from their verify routine. If does not set the */
- /* TGT flags, the required_preauth conditions will not be met and it will */
- /* try again to get enough preauth data from the client. Do not set TGT */
- /* flags here. */
+ /*
+ * It is up to the method-specific verify routine to set the ticket flags to
+ * indicate TKT_FLG_HW_AUTH and/or TKT_FLG_PRE_AUTH. Some methods may
+ * require more than one round of dialog with the client and must return
+ * successfully from their verify routine. If does not set the TGT flags,
+ * the required_preauth conditions will not be met and it will try again to
+ * get enough preauth data from the client. Do not set TGT flags here.
+ */
cleanup:
- /*Note that e_data is an output even in error conditions.*/
- if (out_sc2) {
- krb5_pa_data pa_out;
- krb5_pa_data *pa_array[2];
- pa_array[0] = &pa_out;
- pa_array[1] = NULL;
- pa_out.pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
- retval = encode_krb5_sam_challenge_2(out_sc2, &scratch2);
- krb5_free_sam_challenge_2(context, out_sc2);
- if (retval)
- goto encode_error;
- pa_out.contents = (krb5_octet *) scratch2->data;
- pa_out.length = scratch2->length;
- retval = encode_krb5_padata_sequence(pa_array, e_data);
- krb5_free_data(context, scratch2);
- }
-encode_error: if (sr2)
- krb5_free_sam_response_2(context, sr2);
- if (client_name)
-free(client_name);
-
- return(retval);
+ /*Note that e_data is an output even in error conditions.*/
+ if (out_sc2) {
+ krb5_pa_data pa_out;
+ krb5_pa_data *pa_array[2];
+ pa_array[0] = &pa_out;
+ pa_array[1] = NULL;
+ pa_out.pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
+ retval = encode_krb5_sam_challenge_2(out_sc2, &scratch2);
+ krb5_free_sam_challenge_2(context, out_sc2);
+ if (retval)
+ goto encode_error;
+ pa_out.contents = (krb5_octet *) scratch2->data;
+ pa_out.length = scratch2->length;
+ retval = encode_krb5_padata_sequence(pa_array, e_data);
+ krb5_free_data(context, scratch2);
+ }
+encode_error:
+ krb5_free_sam_response_2(context, sr2);
+ free(client_name);
+ return retval;
}