/* * Decrypt secret key using passwd * The secret key is passed and returned in hex notation. * Once again, the length is a multiple of 16 hex digits */ int xdecrypt(char *secret, char *passwd) { char key[8]; char ivec[8]; char *buf; int err; int len; len = strlen(secret) / 2; if ((buf = malloc((unsigned)len)) == NULL) return(0); hex2bin(len, secret, buf); passwd2des(passwd, key); bzero(ivec, 8); err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec); if (DES_FAILED(err)) { free(buf); return (0); } bin2hex(len, (unsigned char *) buf, secret); free(buf); return (1); }
/* * Decrypt secret key using passwd * The secret key is passed and returned in hex notation. * Once again, the length is a multiple of 16 hex digits */ int xdecrypt (char *secret, char *passwd) { char key[8]; char ivec[8]; char *buf; int err; int len; len = strlen (secret) / 2; buf = malloc ((unsigned) len); hex2bin (len, secret, buf); passwd2des_internal (passwd, key); memset (ivec, 0, 8); err = cbc_crypt (key, buf, len, DES_DECRYPT | DES_HW, ivec); if (DES_FAILED (err)) { free (buf); return 0; } bin2hex (len, (unsigned char *) buf, secret); free (buf); return 1; }
/* * 3. Validate */ static bool authdes_validate(AUTH *auth, struct opaque_auth *rverf) { /* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); struct authdes_verf verf; int status; uint32_t *ixdr; des_block buf; if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) return (false); /* LINTED pointer alignment */ ixdr = (uint32_t *) rverf->oa_base; buf.key.high = (uint32_t) *ixdr++; buf.key.low = (uint32_t) *ixdr++; verf.adv_int_u = (uint32_t) *ixdr++; /* * Decrypt the timestamp */ status = ecb_crypt((char *)&auth->ah_key, (char *)&buf, (u_int) sizeof(des_block), DES_DECRYPT | DES_HW); if (DES_FAILED(status)) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_validate: DES decryption failure"); return (false); } /* * xdr the decrypted timestamp */ /* LINTED pointer alignment */ ixdr = (uint32_t *) buf.c; verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1; verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr); /* * validate */ if (bcmp ((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp, sizeof(struct timeval)) != 0) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_validate: verifier mismatch"); return (false); } /* * We have a nickname now, let's use it */ ad->ad_nickname = verf.adv_nickname; ad->ad_cred.adc_namekind = ADN_NICKNAME; return (true); }
/* * encrypt/decrypt R (val) and password (str) * return FALSE on failure and TRUE on success */ bool_t __npd_cbc_crypt( uint32_t *val, char *str, unsigned int strsize, npd_newpass *buf, unsigned int bufsize, unsigned int mode, des_block *deskey) { int status, i; int32_t *ixdr; des_block ivec; if (bufsize > MAX_KEY_CRYPT_LEN) return (FALSE); ivec.key.low = ivec.key.high = 0; ixdr = (int32_t *)buf; if (mode == DES_ENCRYPT) { if ((strsize + 4) > bufsize) return (FALSE); IXDR_PUT_U_INT32(ixdr, *val); (void) strcpy((char *)buf->pass, str); for (i = strsize; i < __NPD_MAXPASSBYTES; i++) buf->pass[i] = '\0'; status = cbc_crypt((char *)deskey, (char *)buf, bufsize, mode | DES_HW, (char *)&ivec); if (DES_FAILED(status)) return (FALSE); } else { status = cbc_crypt((char *)deskey, (char *)buf, bufsize, mode | DES_HW, (char *)&ivec); if (DES_FAILED(status)) return (FALSE); *val = IXDR_GET_U_INT32(ixdr); if (strlen((char *)buf->pass) > strsize) return (FALSE); (void) strcpy(str, (char *)buf->pass); } return (TRUE); }
/* * 3. Validate */ static bool_t authdes_validate (AUTH *auth, struct opaque_auth *rverf) { struct ad_private *ad = AUTH_PRIVATE (auth); struct authdes_verf verf; int status; register uint32_t *ixdr; if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) return FALSE; ixdr = (uint32_t *) rverf->oa_base; verf.adv_xtimestamp.key.high = *ixdr++; verf.adv_xtimestamp.key.low = *ixdr++; verf.adv_int_u = *ixdr++; /* nickname not XDR'd ! */ /* * Decrypt the timestamp */ status = ecb_crypt ((char *) &auth->ah_key, (char *) &verf.adv_xtimestamp, sizeof (des_block), DES_DECRYPT | DES_HW); if (DES_FAILED (status)) { debug ("authdes_validate: DES decryption failure"); return FALSE; } /* * xdr the decrypted timestamp */ ixdr = (uint32_t *) verf.adv_xtimestamp.c; verf.adv_timestamp.tv_sec = IXDR_GET_U_INT32 (ixdr) + 1; verf.adv_timestamp.tv_usec = IXDR_GET_U_INT32 (ixdr); /* * validate */ if (memcmp ((char *) &ad->ad_timestamp, (char *) &verf.adv_timestamp, sizeof (struct rpc_timeval)) != 0) { debug ("authdes_validate: verifier mismatch\n"); return FALSE; } /* * We have a nickname now, let's use it */ ad->ad_nickname = verf.adv_nickname; ad->ad_cred.adc_namekind = ADN_NICKNAME; return TRUE; }
/* * encrypt/decrypt ID (val1) and R (val2) * return FALSE on failure and TRUE on success */ bool_t __npd_ecb_crypt( uint32_t *val1, uint32_t *val2, des_block *buf, unsigned int bufsize, unsigned int mode, des_block *deskey) { int status; int32_t *ixdr; if (bufsize > MAX_KEY_CRYPT_LEN) return (FALSE); ixdr = (int32_t *)buf; if (mode == DES_ENCRYPT) { (void) memset((char *)buf, 0, bufsize); IXDR_PUT_U_INT32(ixdr, *val1); IXDR_PUT_U_INT32(ixdr, *val2); status = ecb_crypt((char *)deskey, (char *)buf, bufsize, mode | DES_HW); if (DES_FAILED(status)) return (FALSE); } else { status = ecb_crypt((char *)deskey, (char *)buf, bufsize, mode | DES_HW); if (DES_FAILED(status)) return (FALSE); *val1 = IXDR_GET_U_INT32(ixdr); *val2 = IXDR_GET_U_INT32(ixdr); } return (TRUE); }
/* * 2. Marshal */ static bool_t authdes_marshal(AUTH *auth, XDR *xdrs) { /* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); struct authdes_cred *cred = &ad->ad_cred; struct authdes_verf *verf = &ad->ad_verf; des_block cryptbuf[2]; des_block ivec; int status; int len; rpc_inline_t *ixdr; /* * Figure out the "time", accounting for any time difference * with the server if necessary. */ (void)gettimeofday(&ad->ad_timestamp, NULL); ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec; ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec; while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) { ad->ad_timestamp.tv_usec -= USEC_PER_SEC; ad->ad_timestamp.tv_sec++; } /* * XDR the timestamp and possibly some other things, then * encrypt them. */ ixdr = (rpc_inline_t *)cryptbuf; IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec); IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec); if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { IXDR_PUT_U_INT32(ixdr, ad->ad_window); IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1); ivec.key.high = ivec.key.low = 0; status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf, (u_int) 2 * sizeof (des_block), DES_ENCRYPT | DES_HW, (char *)&ivec); } else { status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, (u_int) sizeof (des_block), DES_ENCRYPT | DES_HW); } if (DES_FAILED(status)) { syslog(LOG_ERR, "authdes_marshal: DES encryption failure"); return (FALSE); } ad->ad_verf.adv_xtimestamp = cryptbuf[0]; if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; ad->ad_verf.adv_winverf = cryptbuf[1].key.low; } else { ad->ad_cred.adc_nickname = ad->ad_nickname; ad->ad_verf.adv_winverf = 0; } /* * Serialize the credential and verifier into opaque * authentication data. */ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); } else { len = (1 + 1)*BYTES_PER_XDR_UNIT; } if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { IXDR_PUT_INT32(ixdr, AUTH_DES); IXDR_PUT_INT32(ixdr, len); } else { ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor)); ATTEMPT(xdr_putint32(xdrs, &len)); } ATTEMPT(xdr_authdes_cred(xdrs, cred)); len = (2 + 1)*BYTES_PER_XDR_UNIT; if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { IXDR_PUT_INT32(ixdr, AUTH_DES); IXDR_PUT_INT32(ixdr, len); } else { ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor)); ATTEMPT(xdr_putint32(xdrs, &len)); } ATTEMPT(xdr_authdes_verf(xdrs, verf)); return (TRUE); }
/* * 2. Marshal */ static bool_t authdes_marshal (AUTH *auth, XDR *xdrs) { struct ad_private *ad = AUTH_PRIVATE (auth); struct authdes_cred *cred = &ad->ad_cred; struct authdes_verf *verf = &ad->ad_verf; des_block cryptbuf[2]; des_block ivec; int status; int len; register int32_t *ixdr; struct timeval tval; /* * Figure out the "time", accounting for any time difference * with the server if necessary. */ __gettimeofday (&tval, (struct timezone *) NULL); ad->ad_timestamp.tv_sec = tval.tv_sec + ad->ad_timediff.tv_sec; ad->ad_timestamp.tv_usec = tval.tv_usec + ad->ad_timediff.tv_usec; if (ad->ad_timestamp.tv_usec >= MILLION) { ad->ad_timestamp.tv_usec -= MILLION; ad->ad_timestamp.tv_sec += 1; } /* * XDR the timestamp and possibly some other things, then * encrypt them. * XXX We have a real Year 2038 problem here. */ ixdr = (int32_t *) cryptbuf; IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_sec); IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_usec); if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { IXDR_PUT_U_INT32 (ixdr, ad->ad_window); IXDR_PUT_U_INT32 (ixdr, ad->ad_window - 1); ivec.key.high = ivec.key.low = 0; status = cbc_crypt ((char *) &auth->ah_key, (char *) cryptbuf, 2 * sizeof (des_block), DES_ENCRYPT | DES_HW, (char *) &ivec); } else status = ecb_crypt ((char *) &auth->ah_key, (char *) cryptbuf, sizeof (des_block), DES_ENCRYPT | DES_HW); if (DES_FAILED (status)) { debug ("authdes_marshal: DES encryption failure"); return FALSE; } ad->ad_verf.adv_xtimestamp = cryptbuf[0]; if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; ad->ad_verf.adv_winverf = cryptbuf[1].key.low; } else { ad->ad_cred.adc_nickname = ad->ad_nickname; ad->ad_verf.adv_winverf = 0; } /* * Serialize the credential and verifier into opaque * authentication data. */ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) len = ((1 + 1 + 2 + 1) * BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); else len = (1 + 1) * BYTES_PER_XDR_UNIT; if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) { IXDR_PUT_INT32 (ixdr, AUTH_DES); IXDR_PUT_U_INT32 (ixdr, len); } else { ATTEMPT (xdr_putint32 (xdrs, &auth->ah_cred.oa_flavor)); ATTEMPT (xdr_putint32 (xdrs, &len)); } ATTEMPT (xdr_authdes_cred (xdrs, cred)); len = (2 + 1) * BYTES_PER_XDR_UNIT; if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) { IXDR_PUT_INT32 (ixdr, AUTH_DES); IXDR_PUT_U_INT32 (ixdr, len); } else { ATTEMPT (xdr_putint32 (xdrs, &auth->ah_verf.oa_flavor)); ATTEMPT (xdr_putint32 (xdrs, &len)); } ATTEMPT (xdr_authdes_verf (xdrs, verf)); return TRUE; }