void MD5auth_setkey( keyid_t keyno, int keytype, const uint8_t *key, size_t len ) { symkey * sk; symkey ** bucket; uint8_t * secret; size_t secretsize; DEBUG_ENSURE(keytype <= USHRT_MAX); DEBUG_ENSURE(len < 4 * 1024); /* * See if we already have the key. If so just stick in the * new value. */ bucket = &key_hash[KEYHASH(keyno)]; for (sk = *bucket; sk != NULL; sk = sk->hlink) { if (keyno == sk->keyid) { sk->type = (u_short)keytype; secretsize = len; sk->secretsize = (u_short)secretsize; free(sk->secret); sk->secret = emalloc(secretsize); memcpy(sk->secret, key, secretsize); if (cache_keyid == keyno) { cache_flags = 0; cache_keyid = 0; } return; } } /* * Need to allocate new structure. Do it. */ secretsize = len; secret = emalloc(secretsize); memcpy(secret, key, secretsize); allocsymkey(bucket, keyno, 0, (u_short)keytype, 0, (u_short)secretsize, secret); #ifdef DEBUG if (debug >= 4) { size_t j; printf("auth_setkey: key %d type %d len %d ", (int)keyno, keytype, (int)secretsize); for (j = 0; j < secretsize; j++) printf("%02x", secret[j]); printf("\n"); } #endif }
/* * allocsymkey - common code to allocate and link in symkey * * secret must be allocated with a free-compatible allocator. It is * owned by the referring symkey structure, and will be free()d by * freesymkey(). */ static void allocsymkey( symkey ** bucket, keyid_t id, u_short flags, u_short type, u_long lifetime, u_short secretsize, uint8_t * secret ) { symkey * sk; if (authnumfreekeys < 1) auth_moremem(-1); UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f); DEBUG_ENSURE(sk != NULL); sk->keyid = id; sk->flags = flags; sk->type = type; sk->secretsize = secretsize; sk->secret = secret; sk->lifetime = lifetime; LINK_SLIST(*bucket, sk, hlink); LINK_TAIL_DLIST(key_listhead, sk, llink); authnumfreekeys--; authnumkeys++; }
blocking_pipe_header * receive_blocking_resp_internal( blocking_child * c ) { blocking_pipe_header * removed; #ifdef USE_WORK_PIPE int rc; char scratch[32]; do { rc = read(c->resp_read_pipe, scratch, sizeof(scratch)); } while (-1 == rc && EINTR == errno); #endif removed = c->responses[c->next_workresp]; if (NULL != removed) { c->responses[c->next_workresp] = NULL; c->next_workresp = (1 + c->next_workresp) % c->responses_alloc; DEBUG_ENSURE(CHILD_GONE_RESP == removed || BLOCKING_RESP_MAGIC == removed->magic_sig); } if (CHILD_GONE_RESP == removed) { cleanup_after_child(c); removed = NULL; } return removed; }
/* -------------------------------------------------------------------- * Fetch the next response from the return queue. In case of signalling * via pipe, make sure the pipe is flushed, too. */ blocking_pipe_header * receive_blocking_resp_internal( blocking_child * c ) { blocking_pipe_header * removed; size_t qhead, qtail, slot; #ifdef WORK_PIPE int rc; char scratch[32]; do rc = read(c->resp_read_pipe, scratch, sizeof(scratch)); while (-1 == rc && EINTR == errno); #endif /* >>>> ACCESS LOCKING STARTS >>>> */ wait_for_sem(c->accesslock, NULL); qhead = c->head_response; qtail = c->tail_response; for (removed = NULL; !removed && (qhead != qtail); ++qtail) { slot = qtail % c->responses_alloc; removed = c->responses[slot]; c->responses[slot] = NULL; } c->tail_response = qtail; tickle_sem(c->accesslock); /* <<<< ACCESS LOCKING ENDS <<<< */ if (NULL != removed) { DEBUG_ENSURE(CHILD_GONE_RESP == removed || BLOCKING_RESP_MAGIC == removed->magic_sig); } if (CHILD_GONE_RESP == removed) { cleanup_after_child(c); removed = NULL; } return removed; }
/* * freesymkey - common code to remove a symkey and recycle its entry. */ static void freesymkey( symkey * sk, symkey ** bucket ) { symkey * unlinked; if (sk->secret != NULL) { memset(sk->secret, '\0', sk->secretsize); free(sk->secret); } UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey); DEBUG_ENSURE(sk == unlinked); UNLINK_DLIST(sk, llink); memset((char *)sk + offsetof(symkey, symkey_payload), '\0', sizeof(*sk) - offsetof(symkey, symkey_payload)); LINK_SLIST(authfreekeys, sk, llink.f); authnumkeys--; authnumfreekeys++; }
/* Note: There are two locations below where 'strncpy()' is used. While * this function is a hazard by itself, it's essential that it is used * here. Bug 1243 involved that the secret was filled with NUL bytes * after the first NUL encountered, and 'strlcpy()' simply does NOT have * this behaviour. So disabling the fix and reverting to the buggy * behaviour due to compatibility issues MUST also fill with NUL and * this needs 'strncpy'. Also, the secret is managed as a byte blob of a * given size, and eventually truncating it and replacing the last byte * with a NUL would be a bug. * [email protected] 2015-10-10 */ void MD5auth_setkey( keyid_t keyno, int keytype, const u_char *key, size_t len, KeyAccT *ka ) { symkey * sk; symkey ** bucket; u_char * secret; size_t secretsize; DEBUG_ENSURE(keytype <= USHRT_MAX); DEBUG_ENSURE(len < 4 * 1024); /* * See if we already have the key. If so just stick in the * new value. */ bucket = &key_hash[KEYHASH(keyno)]; for (sk = *bucket; sk != NULL; sk = sk->hlink) { if (keyno == sk->keyid) { /* TALOS-CAN-0054: make sure we have a new buffer! */ if (NULL != sk->secret) { memset(sk->secret, 0, sk->secretsize); free(sk->secret); } sk->secret = emalloc(len); sk->type = (u_short)keytype; secretsize = len; sk->secretsize = (u_short)secretsize; sk->keyacclist = ka; #ifndef DISABLE_BUG1243_FIX memcpy(sk->secret, key, secretsize); #else /* >MUST< use 'strncpy()' here! See above! */ strncpy((char *)sk->secret, (const char *)key, secretsize); #endif if (cache_keyid == keyno) { cache_flags = 0; cache_keyid = 0; cache_keyacclist = NULL; } return; } } /* * Need to allocate new structure. Do it. */ secretsize = len; secret = emalloc(secretsize); #ifndef DISABLE_BUG1243_FIX memcpy(secret, key, secretsize); #else /* >MUST< use 'strncpy()' here! See above! */ strncpy((char *)secret, (const char *)key, secretsize); #endif allocsymkey(bucket, keyno, 0, (u_short)keytype, 0, (u_short)secretsize, secret, ka); #ifdef DEBUG if (debug >= 4) { size_t j; printf("auth_setkey: key %d type %d len %d ", (int)keyno, keytype, (int)secretsize); for (j = 0; j < secretsize; j++) printf("%02x", secret[j]); printf("\n"); } #endif }