From a2cf039307a9d11a9c7fc2670252ea7a72aa5176 Mon Sep 17 00:00:00 2001 From: Chaskiel Grundman Date: Sat, 9 Feb 2013 12:01:37 -0500 Subject: [PATCH] Add rxkad server hook function to decrypt more types of tokens Allow tokens to be encrypted with algorithms other than DES. The security object owner must provide an implementation by calling rxkad_SetAltDecryptProc. Make sure plainsiz is initialized before calling the alternate decrypt proc. --- src/rxkad/private_data.h | 1 + src/rxkad/rxkad.p.h | 5 ++++ src/rxkad/rxkad_prototypes.h | 5 +++- src/rxkad/rxkad_server.c | 13 +++++++++- src/rxkad/ticket5.c | 49 +++++++++++++++++++++--------------- 5 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/rxkad/private_data.h b/src/rxkad/private_data.h index 1d762ff3a..c80512833 100644 --- a/src/rxkad/private_data.h +++ b/src/rxkad/private_data.h @@ -78,6 +78,7 @@ struct rxkad_sprivate { int (*get_key) (); /* func. of kvno and server key ptr */ int (*user_ok) (); /* func called with new client name */ afs_uint32 flags; /* configuration flags */ + rxkad_alt_decrypt_func alt_decrypt; }; /* private data in server-side connection */ diff --git a/src/rxkad/rxkad.p.h b/src/rxkad/rxkad.p.h index ce052dfd0..a1cdf23c1 100644 --- a/src/rxkad/rxkad.p.h +++ b/src/rxkad/rxkad.p.h @@ -93,6 +93,11 @@ typedef char rxkad_level; extern int rxkad_EpochWasSet; /* TRUE => we called rx_SetEpoch */ +/* An alternate decryption function for rxkad. Using the given kvno and + * enctype, decrypt the input data + length to output data + length. */ +typedef int (*rxkad_alt_decrypt_func)(int, int, void *, size_t, void *, + size_t *); + #include "rxkad_prototypes.h" #endif /* OPENAFS_RXKAD_RXKAD_H */ diff --git a/src/rxkad/rxkad_prototypes.h b/src/rxkad/rxkad_prototypes.h index a2c3517ff..a297d3bee 100644 --- a/src/rxkad/rxkad_prototypes.h +++ b/src/rxkad/rxkad_prototypes.h @@ -124,6 +124,8 @@ extern afs_int32 rxkad_SetConfiguration(struct rx_securityClass *aobj, struct rx_connection *aconn, rx_securityConfigVariables atype, void * avalue, void **aresult); +extern int rxkad_SetAltDecryptProc(struct rx_securityClass *aobj, + rxkad_alt_decrypt_func alt_decrypt); /* ticket.c */ extern int tkt_DecodeTicket(char *asecret, afs_int32 ticketLen, @@ -149,6 +151,7 @@ extern int tkt_DecodeTicket5(char *ticket, afs_int32 ticket_len, char *get_key_rock, int serv_kvno, char *name, char *inst, char *cell, char *session_key, afs_int32 * host, afs_int32 * start, - afs_int32 * end, afs_int32 disableDotCheck); + afs_int32 * end, afs_int32 disableDotCheck, + rxkad_alt_decrypt_func alt_decrypt); #endif diff --git a/src/rxkad/rxkad_server.c b/src/rxkad/rxkad_server.c index 3a15a7b21..a334f4c0d 100644 --- a/src/rxkad/rxkad_server.c +++ b/src/rxkad/rxkad_server.c @@ -326,7 +326,8 @@ rxkad_CheckResponse(struct rx_securityClass *aobj, tkt_DecodeTicket5(tix, tlen, tsp->get_key, tsp->get_key_rock, kvno, client.name, client.instance, client.cell, &sessionkey, &host, &start, &end, - tsp->flags & RXS_CONFIG_FLAGS_DISABLE_DOTCHECK); + tsp->flags & RXS_CONFIG_FLAGS_DISABLE_DOTCHECK, + tsp->alt_decrypt); if (code) return code; } @@ -474,3 +475,13 @@ afs_int32 rxkad_SetConfiguration(struct rx_securityClass *aobj, } return 0; } + +int rxkad_SetAltDecryptProc(struct rx_securityClass *aobj, + rxkad_alt_decrypt_func alt_decrypt) +{ + struct rxkad_sprivate *private = + (struct rxkad_sprivate *)aobj->privateData; + + private->alt_decrypt = alt_decrypt; + return 0; +} diff --git a/src/rxkad/ticket5.c b/src/rxkad/ticket5.c index a83f7fed8..8fd0f02de 100644 --- a/src/rxkad/ticket5.c +++ b/src/rxkad/ticket5.c @@ -193,7 +193,8 @@ tkt_DecodeTicket5(char *ticket, afs_int32 ticket_len, int (*get_key) (char *, int, struct ktc_encryptionKey *), char *get_key_rock, int serv_kvno, char *name, char *inst, char *cell, char *session_key, afs_int32 * host, - afs_int32 * start, afs_int32 * end, afs_int32 disableCheckdot) + afs_int32 * start, afs_int32 * end, afs_int32 disableCheckdot, + rxkad_alt_decrypt_func alt_decrypt) { char plain[MAXKRB5TICKETLEN]; struct ktc_encryptionKey serv_key; @@ -234,33 +235,41 @@ tkt_DecodeTicket5(char *ticket, afs_int32 ticket_len, v5_serv_kvno = *t5.enc_part.kvno; } - /* Check that the key type really fit into 8 bytes */ + /* check ticket */ + if (t5.enc_part.cipher.length > sizeof(plain)) + goto bad_ticket; switch (t5.enc_part.etype) { case ETYPE_DES_CBC_CRC: case ETYPE_DES_CBC_MD4: case ETYPE_DES_CBC_MD5: + /* Check that the key type really fit into 8 bytes */ + if (t5.enc_part.cipher.length % 8 != 0) + goto bad_ticket; + + code = (*get_key) (get_key_rock, v5_serv_kvno, &serv_key); + if (code) + goto unknown_key; + + /* Decrypt data here, save in plain, assume it will shrink */ + code = + krb5_des_decrypt(&serv_key, t5.enc_part.etype, + t5.enc_part.cipher.data, + t5.enc_part.cipher.length, plain, &plainsiz); + if (code != 0) + goto bad_ticket; break; default: - goto unknown_key; + if (alt_decrypt != NULL) { + plainsiz = sizeof(plain); + code = alt_decrypt(v5_serv_kvno, t5.enc_part.etype, + t5.enc_part.cipher.data, + t5.enc_part.cipher.length, plain, &plainsiz); + if (code != 0) + goto cleanup; + } else + goto unknown_key; } - /* check ticket */ - if (t5.enc_part.cipher.length > sizeof(plain) - || t5.enc_part.cipher.length % 8 != 0) - goto bad_ticket; - - code = (*get_key) (get_key_rock, v5_serv_kvno, &serv_key); - if (code) - goto unknown_key; - - /* Decrypt data here, save in plain, assume it will shrink */ - code = - krb5_des_decrypt(&serv_key, t5.enc_part.etype, - t5.enc_part.cipher.data, t5.enc_part.cipher.length, - plain, &plainsiz); - if (code != 0) - goto bad_ticket; - /* Decode ticket */ code = decode_EncTicketPart(plain, plainsiz, &decr_part, &siz); if (code != 0) -- 2.39.5