/*
- * $Source$
- * $Author$
+ * lib/krb5/krb/mk_req_ext.c
*
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
- * Export of this software from the United States of America is assumed
- * to require a specific license from the United States Government.
+ * 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.
*
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
* krb5_mk_req_extended()
*/
-#if !defined(lint) && !defined(SABER)
-static char rcsid_mk_req_ext_c[] =
-"$Id$";
-#endif /* !lint & !SABER */
-#include <krb5/krb5.h>
-#include <krb5/asn1.h>
-
-#include <krb5/libos.h>
-#include <krb5/los-proto.h>
-
-#include <krb5/ext-proto.h>
+#include "k5-int.h"
+#include "auth_con.h"
/*
Formats a KRB_AP_REQ message into outbuf, with more complete options than
returns system errors
*/
-static krb5_error_code generate_authenticator PROTOTYPE((krb5_authenticator *,
- const krb5_creds *,
- const krb5_checksum *,
- krb5_keyblock *,
- krb5_int32 ));
-
-krb5_error_code
-krb5_mk_req_extended(ap_req_options, checksum, kdc_options,
- sequence, newkey, ccache, creds, authentp, outbuf)
-const krb5_flags ap_req_options;
-const krb5_checksum *checksum;
-const krb5_flags kdc_options;
-krb5_int32 sequence;
-krb5_keyblock **newkey;
-krb5_ccache ccache;
-krb5_creds *creds;
-krb5_authenticator *authentp;
-krb5_data *outbuf;
+
+static krb5_error_code
+krb5_generate_authenticator PROTOTYPE((krb5_context,
+ krb5_authenticator *, krb5_principal,
+ const krb5_checksum *, krb5_keyblock *,
+ krb5_int32, krb5_authdata ** ));
+
+KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
+krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds,
+ outbuf)
+ krb5_context context;
+ krb5_auth_context FAR * auth_context;
+ const krb5_flags ap_req_options;
+ krb5_data FAR * in_data;
+ krb5_creds FAR * in_creds;
+ krb5_data FAR * outbuf;
{
- krb5_error_code retval;
+ krb5_error_code retval;
+ krb5_checksum checksum;
+ krb5_checksum *checksump = 0;
+ krb5_auth_context new_auth_context;
+
krb5_ap_req request;
- krb5_authenticator authent;
- krb5_data *scratch;
- krb5_enctype etype;
- krb5_encrypt_block eblock;
+ krb5_data *scratch = 0;
krb5_data *toutbuf;
- if ((ap_req_options & AP_OPTS_USE_SESSION_KEY) &&
- !creds->ticket.length)
+ request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK;
+ request.authenticator.ciphertext.data = 0;
+ request.ticket = 0;
+
+ if (!in_creds->ticket.length)
return(KRB5_NO_TKT_SUPPLIED);
- if (!creds->ticket.length) {
- /* go get creds */
- if (retval = krb5_get_credentials(kdc_options,
- ccache,
- creds))
- return(retval);
- }
- /* verify a valid etype is available */
- if (!valid_keytype(creds->keyblock.keytype))
- return KRB5_PROG_KEYTYPE_NOSUPP;
-
- etype = krb5_keytype_array[creds->keyblock.keytype]->system->proto_enctype;
-
- if (!valid_etype(etype))
- return KRB5_PROG_ETYPE_NOSUPP;
-
- request.ap_options = ap_req_options;
/* we need a native ticket */
- if (retval = decode_krb5_ticket(&creds->ticket, &request.ticket))
- return(retval);
-
-#define cleanup_ticket() krb5_free_ticket(request.ticket)
- if (newkey) {
- if (retval = krb5_generate_subkey(&creds->keyblock, newkey)) {
- cleanup_ticket();
- return retval;
- }
- }
-#define cleanup_key() {if (newkey) krb5_free_keyblock(*newkey);}
- if (retval = generate_authenticator(&authent, creds, checksum,
- newkey ? *newkey : 0,
- sequence)) {
- cleanup_key();
- cleanup_ticket();
- return retval;
- }
- if (authentp) {
- *authentp = authent;
- /* Null out these fields, to prevent pointer sharing problems
- * The caller won't need these fields anyway, since they were
- * supplied by the caller
- */
- authentp->client = NULL;
- authentp->checksum = NULL;
- }
- /* encode it before encrypting */
- retval = encode_krb5_authenticator(&authent, &scratch);
- if (retval) {
- cleanup_key();
- cleanup_ticket();
+ if ((retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket)))
return(retval);
+
+ /* verify that the ticket is not expired */
+ if ((retval = krb5_validate_times(context, &in_creds->times)) != 0)
+ goto cleanup;
+
+ /* generate auth_context if needed */
+ if (*auth_context == NULL) {
+ if ((retval = krb5_auth_con_init(context, &new_auth_context)))
+ goto cleanup;
+ *auth_context = new_auth_context;
}
-#define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
-krb5_free_data(scratch); }
-
- /* put together an eblock for this encryption */
-
- krb5_use_cstype(&eblock, etype);
- request.authenticator.etype = etype;
- request.authenticator.kvno = 0; /* XXX user set? */
- request.authenticator.ciphertext.length =
- krb5_encrypt_size(scratch->length, eblock.crypto_entry);
- /* add padding area, and zero it */
- if (!(scratch->data = realloc(scratch->data,
- request.authenticator.ciphertext.length))) {
- /* may destroy scratch->data */
- xfree(scratch);
- retval = ENOMEM;
- goto clean_ticket;
- }
- memset(scratch->data + scratch->length, 0,
- request.authenticator.ciphertext.length - scratch->length);
- if (!(request.authenticator.ciphertext.data =
- malloc(request.authenticator.ciphertext.length))) {
- retval = ENOMEM;
- goto clean_scratch;
+ /* set auth context keyblock */
+ if ((retval = krb5_copy_keyblock(context, &in_creds->keyblock,
+ &((*auth_context)->keyblock))))
+ goto cleanup;
+
+ /* generate seq number if needed */
+ if ((((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
+ || ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
+ && ((*auth_context)->local_seq_number == 0))
+ if ((retval = krb5_generate_seq_number(context, &in_creds->keyblock,
+ &(*auth_context)->local_seq_number)))
+ goto cleanup;
+
+
+ /* generate subkey if needed */
+ if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->local_subkey)) {
+ /* Provide some more fodder for random number code.
+ This isn't strong cryptographically; the point here is not
+ to guarantee randomness, but to make it less likely that multiple
+ sessions could pick the same subkey. */
+ struct {
+ krb5_int32 sec, usec;
+ } rnd_data;
+ krb5_data d;
+ krb5_crypto_us_timeofday (&rnd_data.sec, &rnd_data.usec);
+ d.length = sizeof (rnd_data);
+ d.data = (char *) &rnd_data;
+ (void) krb5_c_random_seed (context, &d);
+
+ if ((retval = krb5_generate_subkey(context, &(in_creds)->keyblock,
+ &(*auth_context)->local_subkey)))
+ goto cleanup;
}
-#define cleanup_encpart() {\
-(void) memset(request.authenticator.ciphertext.data, 0,\
- request.authenticator.ciphertext.length); \
-free(request.authenticator.ciphertext.data); \
-request.authenticator.ciphertext.length = 0; \
-request.authenticator.ciphertext.data = 0;}
-
- /* do any necessary key pre-processing */
- if (retval = krb5_process_key(&eblock, &creds->keyblock)) {
- goto clean_encpart;
+ if (in_data) {
+ if ((*auth_context)->req_cksumtype == 0x8003) {
+ /* XXX Special hack for GSSAPI */
+ checksum.checksum_type = 0x8003;
+ checksum.length = in_data->length;
+ checksum.contents = (krb5_octet *) in_data->data;
+ } else {
+ if ((retval = krb5_c_make_checksum(context,
+ (*auth_context)->req_cksumtype,
+ (*auth_context)->keyblock,
+ KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
+ in_data, &checksum)))
+ goto cleanup_cksum;
+ }
+ checksump = &checksum;
}
-#define cleanup_prockey() {(void) krb5_finish_key(&eblock);}
-
- /* call the encryption routine */
- if (retval = krb5_encrypt((krb5_pointer) scratch->data,
- (krb5_pointer) request.authenticator.ciphertext.data,
- scratch->length, &eblock, 0)) {
- goto clean_prockey;
+ /* Generate authenticator */
+ if (((*auth_context)->authentp = (krb5_authenticator *)malloc(sizeof(
+ krb5_authenticator))) == NULL) {
+ retval = ENOMEM;
+ goto cleanup_cksum;
}
- /* authenticator now assembled-- do some cleanup */
- cleanup_scratch();
+ if ((retval = krb5_generate_authenticator(context,
+ (*auth_context)->authentp,
+ (in_creds)->client, checksump,
+ (*auth_context)->local_subkey,
+ (*auth_context)->local_seq_number,
+ (in_creds)->authdata)))
+ goto cleanup_cksum;
+
+ /* encode the authenticator */
+ if ((retval = encode_krb5_authenticator((*auth_context)->authentp,
+ &scratch)))
+ goto cleanup_cksum;
+
+ /* Null out these fields, to prevent pointer sharing problems;
+ * they were supplied by the caller
+ */
+ (*auth_context)->authentp->client = NULL;
+ (*auth_context)->authentp->checksum = NULL;
+ (*auth_context)->authentp->authorization_data = NULL;
- if (retval = krb5_finish_key(&eblock)) {
- cleanup_encpart();
- return retval;
+ /* call the encryption routine */
+ if ((retval = krb5_encrypt_helper(context, &in_creds->keyblock,
+ KRB5_KEYUSAGE_AP_REQ_AUTH,
+ scratch, &request.authenticator)))
+ goto cleanup_cksum;
+
+ if ((retval = encode_krb5_ap_req(&request, &toutbuf)))
+ goto cleanup_cksum;
+#ifdef HAVE_C_STRUCTURE_ASSIGNMENT
+ *outbuf = *toutbuf;
+#else
+ memcpy(outbuf, toutbuf, sizeof(krb5_data));
+#endif
+
+ krb5_xfree(toutbuf);
+
+cleanup_cksum:
+ if (checksump && checksump->checksum_type != 0x8003)
+ free(checksump->contents);
+
+cleanup:
+ if (request.ticket)
+ krb5_free_ticket(context, request.ticket);
+ if (request.authenticator.ciphertext.data) {
+ (void) memset(request.authenticator.ciphertext.data, 0,
+ request.authenticator.ciphertext.length);
+ free(request.authenticator.ciphertext.data);
}
-
- if (!(retval = encode_krb5_ap_req(&request, &toutbuf))) {
- *outbuf = *toutbuf;
- xfree(toutbuf);
+ if (scratch) {
+ memset(scratch->data, 0, scratch->length);
+ krb5_xfree(scratch->data);
+ krb5_xfree(scratch);
}
- cleanup_ticket();
- cleanup_encpart();
- return retval;
-
- clean_prockey:
- cleanup_prockey();
- clean_encpart:
- cleanup_encpart();
- clean_scratch:
- cleanup_scratch();
- clean_ticket:
- cleanup_key();
- cleanup_ticket();
-
return retval;
}
static krb5_error_code
-generate_authenticator(authent, creds, cksum, key, seq_number)
-krb5_authenticator *authent;
-const krb5_creds *creds;
-const krb5_checksum *cksum;
-krb5_keyblock *key;
-krb5_int32 seq_number;
+krb5_generate_authenticator(context, authent, client, cksum, key, seq_number, authorization)
+ krb5_context context;
+ krb5_authenticator *authent;
+ krb5_principal client;
+ const krb5_checksum *cksum;
+ krb5_keyblock *key;
+ krb5_int32 seq_number;
+ krb5_authdata **authorization;
{
- authent->client = creds->client;
+ krb5_error_code retval;
+
+ authent->client = client;
authent->checksum = (krb5_checksum *)cksum;
- authent->subkey = key;
+ if (key) {
+ retval = krb5_copy_keyblock(context, key, &authent->subkey);
+ if (retval)
+ return retval;
+ } else
+ authent->subkey = 0;
authent->seq_number = seq_number;
+ authent->authorization_data = authorization;
- return(krb5_us_timeofday(&authent->ctime, &authent->cusec));
+ return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec));
}