/* * auth_resize_hashtable * * Size hash table to average 4 or fewer entries per bucket initially, * within the bounds of at least 4 and no more than 15 bits for the hash * table index. Populate the hash table. */ static void auth_resize_hashtable(void) { u_long totalkeys; u_short hashbits; u_short hash; size_t newalloc; symkey * sk; totalkeys = authnumkeys + authnumfreekeys; hashbits = auth_log2(totalkeys / 4.0) + 1; hashbits = max(4, hashbits); hashbits = min(15, hashbits); authhashbuckets = 1 << hashbits; authhashmask = authhashbuckets - 1; newalloc = authhashbuckets * sizeof(key_hash[0]); key_hash = erealloc(key_hash, newalloc); memset(key_hash, '\0', newalloc); ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) hash = KEYHASH(sk->keyid); LINK_SLIST(key_hash[hash], sk, hlink); ITER_DLIST_END() }
/* * auth_delkeys - delete non-autokey untrusted keys, and clear all info * except the trusted bit of non-autokey trusted keys, in * preparation for rereading the keys file. */ void auth_delkeys(void) { symkey * sk; ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) if (sk->keyid > NTP_MAXKEY) { /* autokey */ continue; } /* * Don't lose info as to which keys are trusted. Make * sure there are no dangling pointers! */ if (KEY_TRUSTED & sk->flags) { if (sk->secret != NULL) { memset(sk->secret, 0, sk->secretsize); free(sk->secret); sk->secret = NULL; /* TALOS-CAN-0054 */ } sk->secretsize = 0; sk->lifetime = 0; } else { freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); } ITER_DLIST_END() }
/* * authistrusted - determine whether a key is trusted */ int authistrusted( keyid_t keyno ) { struct savekey *sk; if (keyno == cache_keyid) return ((cache_flags & KEY_TRUSTED) != 0); authkeyuncached++; sk = key_hash[KEYHASH(keyno)]; while (sk != 0) { if (keyno == sk->keyid) break; sk = sk->next; } if (sk == 0) { authkeynotfound++; return (0); } else if (!(sk->flags & KEY_TRUSTED)) { authkeynotfound++; return (0); } return (1); }
void feed_key(int skey,int state,int chr) { int kk; u_short km=map_xkey(skey,state,chr); static u_short lastofs, endofs; u_short hh=KEYHASH(km); if (km==0xffff) return; if (!kst) { state0: kst=0; lastofs=ckdefhash[hh]; endofs=ckdefhash[hh+1]; while (lastofs<endofs && ckdef[lastofs].kcode[0]!=km) lastofs++; if (ckdef[lastofs].kcode[0]!=km) return; else kst=1; if (ckdef[lastofs].klen==1) goto match; return; } else { while (lastofs<endofs && (ckdef[lastofs].kcode[kst]!=km)||ckdef[lastofs].klen<kst) lastofs++; if (lastofs==endofs) goto state0; kst++; if (kst==ckdef[lastofs].klen) goto match; else return; } match: kst=0; kk=lastofs; if (!ckdef[kk].type) { if (readonly) { message(4,"Readonly mode"); return; } if (rec_mac) { if (last_str) { /* append it */ strcat(last_str, ckdef[kk].cmd); mac_ptr+=strlen(ckdef[kk].cmd); } else { *(mac_ptr++)=0; strcpy(last_str=mac_ptr, ckdef[kk].cmd); mac_ptr+=strlen(ckdef[kk].cmd)+1; mac_cnt++; } ck_mac_size(); } K_PutStr(ckdef[kk].cmd); disp_fname(); disp_cur_pos(); show_cursor_w(); return; } else { ExecCommand(ckdef[kk].cmd,ckdef[kk].type); } }
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 }
/* * authhavekey - return one and cache the key, if known and trusted. */ int authhavekey( keyid_t keyno ) { struct savekey *sk; authkeylookups++; if (keyno == 0 || keyno == cache_keyid) return (1); /* * Seach the bin for the key. If found and the key type * is zero, somebody marked it trusted without specifying * a key or key type. In this case consider the key missing. */ authkeyuncached++; sk = key_hash[KEYHASH(keyno)]; while (sk != NULL) { if (keyno == sk->keyid) { if (sk->type == 0) { authkeynotfound++; return (0); } break; } sk = sk->next; } /* * If the key is not found, or if it is found but not trusted, * the key is not considered found. */ if (sk == NULL) { authkeynotfound++; return (0); } if (!(sk->flags & KEY_TRUSTED)) { authnokey++; return (0); } /* * The key is found and trusted. Initialize the key cache. */ cache_keyid = sk->keyid; cache_type = sk->type; cache_flags = sk->flags; cache_key = sk->k.MD5_key; cache_keylen = sk->keylen; return (1); }
/* * authhavekey - return TRUE and cache the key, if zero or both known * and trusted. */ int authhavekey( keyid_t id ) { symkey * sk; authkeylookups++; if (0 == id || cache_keyid == id) { return TRUE; } /* * Seach the bin for the key. If found and the key type * is zero, somebody marked it trusted without specifying * a key or key type. In this case consider the key missing. */ authkeyuncached++; for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) { if (id == sk->keyid) { if (0 == sk->type) { authkeynotfound++; return FALSE; } break; } } /* * If the key is not found, or if it is found but not trusted, * the key is not considered found. */ if (NULL == sk) { authkeynotfound++; return FALSE; } if (!(KEY_TRUSTED & sk->flags)) { authnokey++; return FALSE; } /* * The key is found and trusted. Initialize the key cache. */ cache_keyid = sk->keyid; cache_type = sk->type; cache_flags = sk->flags; cache_secret = sk->secret; cache_secretsize = sk->secretsize; cache_keyacclist = sk->keyacclist; return TRUE; }
/* * auth_agekeys - delete keys whose lifetimes have expired */ void auth_agekeys(void) { symkey * sk; ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) if (sk->lifetime > 0 && current_time > sk->lifetime) { freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); authkeyexpired++; } ITER_DLIST_END() DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n", current_time, authnumkeys, authkeyexpired)); }
/* * auth_findkey - find a key in the hash table */ struct savekey * auth_findkey( keyid_t id ) { symkey * sk; for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) { if (id == sk->keyid) { return sk; } } return NULL; }
/* * auth_findkey - find a key in the hash table */ struct savekey * auth_findkey( keyid_t keyno ) { struct savekey *sk; sk = key_hash[KEYHASH(keyno)]; while (sk != 0) { if (keyno == sk->keyid) return (sk); sk = sk->next; } return (0); }
/* * auth_havekey - return true if the key id is zero or known */ int auth_havekey( keyid_t id ) { symkey * sk; if (0 == id || cache_keyid == id) { return true; } for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) { if (id == sk->keyid) { return true; } } return false; }
/* * auth_havekey - return one if the key is known */ int auth_havekey( keyid_t keyno ) { struct savekey *sk; if (keyno == 0 || (keyno == cache_keyid)) return (1); sk = key_hash[KEYHASH(keyno)]; while (sk != 0) { if (keyno == sk->keyid) return (1); sk = sk->next; } return (0); }
static void free_auth_mem(void) { symkey * sk; symkey_alloc * alloc; symkey_alloc * next_alloc; while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) { freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); } free(key_hash); key_hash = NULL; cache_keyid = 0; cache_flags = 0; for (alloc = authallocs; alloc != NULL; alloc = next_alloc) { next_alloc = alloc->link; free(alloc->mem); } authfreekeys = NULL; authnumfreekeys = 0; }
/* * auth_delkeys - delete untrusted keys, and clear all info * except the trusted bit of trusted keys, in * preparation for rereading the keys file. */ void auth_delkeys(void) { symkey * sk; ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) /* * Don't lose info as to which keys are trusted. */ if (KEY_TRUSTED & sk->flags) { if (sk->secret != NULL) { memset(sk->secret, '\0', sk->secretsize); free(sk->secret); sk->secret = NULL; } sk->secretsize = 0; sk->lifetime = 0; } else { freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); } ITER_DLIST_END() }
/* * authistrusted - determine whether a key is trusted */ int authistrusted( keyid_t keyno ) { symkey * sk; symkey ** bucket; if (keyno == cache_keyid) return !!(KEY_TRUSTED & cache_flags); authkeyuncached++; bucket = &key_hash[KEYHASH(keyno)]; for (sk = *bucket; sk != NULL; sk = sk->hlink) { if (keyno == sk->keyid) break; } if (NULL == sk || !(KEY_TRUSTED & sk->flags)) { authkeynotfound++; return false; } return true; }
/* * authistrustedip - determine if the IP is OK for the keyid */ int authistrustedip( keyid_t keyno, sockaddr_u * sau ) { symkey * sk; symkey ** bucket; KeyAccT * kal; KeyAccT * k; if (keyno == cache_keyid) kal = cache_keyacclist; else { authkeyuncached++; bucket = &key_hash[KEYHASH(keyno)]; for (sk = *bucket; sk != NULL; sk = sk->hlink) { if (keyno == sk->keyid) break; } if (NULL == sk || !(KEY_TRUSTED & sk->flags)) { INSIST(!"authistrustedip: keyid not found/trusted!"); return FALSE; } kal = sk->keyacclist; } if (NULL == kal) return TRUE; for (k = kal; k; k = k->next) { if (SOCK_EQ(&k->addr, sau)) return TRUE; } return FALSE; }
LoadTedrc(char *tedname, int depth, int kdefmapno) { FILE *fp; char ss[8192],ibuf[2048],*tt,*uu,*vv,*ww,*xx; int len,i,j,lno; int hdef[128]; extern int X_inited; KEYDEF *kdef=kdefmap[kdefmapno]; int kdefno=kdefno_m[kdefmapno]; if ((fp=init_tedrc_fname(tedname, depth))==NULL) return 1; if (kdefno && !depth) { for(j=0;j<kdefno;j++) free(kdef[j].cmd); if (!kdefmapno) free_lang(); free(kdef); kdefmap[kdefmapno]=NULL; if (kdefmapno) { free(mode_str_m[kdefmapno]); mode_str_m[kdefmapno]=NULL; } kdef=NULL; } #if 0 printf("-- %d %d %s\n",depth, kdefmapno, ftedrc); #endif if (kdef==NULL) { MAX_KEY_DEF=280; if ((kdef=mmalloc(sizeof(KEYDEF)*MAX_KEY_DEF,"LoadTedrc"))==NULL) exit(1); kdefmap[kdefmapno]=kdef; kdefno_m[kdefmapno]=kdefno=0; } if (!depth) qsort(kmap,kname_no,sizeof(KEYMAP),qcmpxk); tedrcfname=tedname; lno=0; while (!feof(fp)) { int next_l; ss[0]=0; next_l=0; for(;;) { lno++; len=mfgets(ibuf,sizeof(ibuf),fp); if (!len) { next_l=1; break; } if (ibuf[len-1]=='\n') ibuf[--len]=0; if (!len) { next_l=1; break; } while (len && (ibuf[len-1]==' '||ibuf[len-1]==9)) len--; if (!len) { next_l=1; break; } if (ibuf[len-1]=='\\') { ibuf[len-1]=0; strcat(ss,ibuf); } else { strcat(ss,ibuf); break; } } if (next_l) continue; tt=skip_spc(ss); uu=to_spc(tt); vv=skip_spc(uu); *uu=0; if (tt[0]=='#') continue; if (!strcmp(tt,"d")) { ww=to_spc(vv); if (!(*vv)) lper(tedname,lno,"argument expected"); kdef[kdefno].klen=parse_key(tedname, lno,vv,ww,kdef[kdefno].kcode); if ((i=kcode_exist(kdefno,kdef,kdefno))<kdefno) free(kdef[i].cmd); xx=skip_spc(ww); kdef[i].cmd=strdup(parse_Cstr(tedname, lno,xx,&uu)); kdef[i].type=0; if (i==kdefno) incr_kdefno(&kdef,kdefmapno,&kdefno); continue; } else if (!strcmp(tt,"f")) { ww=to_spc(vv); if (!(*vv)) lper(tedname,lno,"argument expected"); kdef[kdefno].klen=parse_key(tedname, lno,vv,ww,kdef[kdefno].kcode); if ((i=kcode_exist(kdefno,kdef,kdefno))<kdefno) free(kdef[i].cmd); xx=skip_spc(ww); if (parse_stmt(tedname, lno,xx,&kdef[i].cmd,&kdef[i].type)) { if (i==kdefno) incr_kdefno(&kdef,kdefmapno,&kdefno); } continue; } if (kdefmapno) lper(tedname,lno,"%s for LoadKeyDefInto can accept 'f' and 'd' command only", tedname); if (!strcmp(tt,"s")) { ww=to_spc(vv); xx=skip_spc(ww); *ww=0; for(i=0;i<sizeof(locolor)/sizeof(locolor[0]);i++) if (!strcmp(vv,locolor[i].cname)) break; if (i==sizeof(locolor)/sizeof(locolor[0])) lper(tedname,lno,"Unknown Def color %s",vv); ww=to_spc(xx); *ww=0; strcpy(locolor[i].caddr,xx); } else if (!strcmp(tt,"set")) { ww=to_spc(vv); xx=skip_spc(ww); tt=to_spc(xx); if (!(*ww)) lper(tedname,lno,"argument expected"); *ww=0; for(i=0;i<sizeof(sets)/sizeof(sets[0]);i++) if (!strcmp(sets[i].sname,vv)) break; if (i==sizeof(sets)/sizeof(sets[0])) lper2(tedname,lno,"Unknown set %s",vv); else { *tt=0; *(sets[i].saddr)=atoi(xx); } } else if (!strcmp(tt,"lang") && !depth) { extern char DirectCommentChars[]; int keywcnt=3,LangIdx,ColIdx,AllocN=32,kwidx, MaxKeywordLen=0; char *ff; KW *kw; if (depth) p_err("cannot define 'lang' in include %s", tedname); tt=parse_Cstr(tedname, lno,vv,&uu); i=strlen(tt)+2; if ((vv=mmalloc(i,"LoadTedrc"))==NULL) exit(1); if ((kw=mmalloc(AllocN*sizeof(KW),"LoadTedrc 2"))==NULL) exit(1); LangExt[LangN]=strcat(strcpy(vv,tt)," "); kw[0].coloridx=ColorCnt; strcpy(pc_color[ColorCnt].fg_str,getstr(uu,&vv)); strcpy(pc_color[ColorCnt++].bg_str,getstr(vv,&uu)); uu=skip_spc(uu); DirectCommentChars[LangN]=*uu; kw[1].coloridx=ColorCnt; strcpy(pc_color[ColorCnt].fg_str,getstr(uu+1,&vv)); strcpy(pc_color[ColorCnt++].bg_str,getstr(vv,&uu)); kw[2].coloridx=ColorCnt; strcpy(pc_color[ColorCnt].fg_str,getstr(uu+1,&vv)); strcpy(pc_color[ColorCnt++].bg_str,getstr(vv,&uu)); for(;;) { if (!*uu) break; strcpy(pc_color[ColorCnt].fg_str,getstr(uu+1,&vv)); strcpy(pc_color[ColorCnt].bg_str,getstr(vv,&uu)); uu=skip_spc(uu); ww=tt=parse_Cstr(tedname, lno,uu,&vv); uu=vv; xx=tt+strlen(tt); for(;;) { char *pstr; tt=to_spc(ww); vv=skip_spc(tt); *(tt)=0; if (pstr=strchr(ww,'(')) { kw[keywcnt].arg=strdup(pstr); *pstr=0; } else kw[keywcnt].arg=0; kw[keywcnt].keyword=strdup(ww); if (strlen(ww) > MaxKeywordLen) MaxKeywordLen=strlen(ww); kw[keywcnt].coloridx=ColorCnt; #if 0 printf("%d %d %d %s\n",LangN,keywcnt, ColorCnt, kw[keywcnt].keyword); #endif keywcnt++; if (keywcnt+3>=AllocN) { AllocN+=32; if ((kw=mrealloc(kw,AllocN*sizeof(KW),"LoadTedrc 3"))==NULL) exit(1); } ww=vv; if (ww==xx) break; } ColorCnt++; } qsort(kw+3,keywcnt-3,sizeof(KW), kwcmp); LangKw[LangN]=kw; LangMaxKeywordLen[LangN]=MaxKeywordLen; LangKwN[LangN++]=keywcnt; if (LangN>=MaxLang) { error("Too many languages defined"); error("Remove unused language in tedrc or modify ted.h and recompile"); exit(1); } } else if (!strcmp(tt,"include")) { if (depth > 10) { error("include too many level ??"); continue; } ww=to_spc(vv); xx=skip_spc(ww); if (!(*vv)) lper(tedname,lno,"argument expected"); *ww=0; LoadTedrc(vv,depth+1,kdefmapno); tedrcfname=tedname; } else if (!strcmp(tt,"filebrowser")) { ww=to_spc(vv); xx=skip_spc(ww); if (!(*vv)) lper(tedname,lno,"argument expected"); init_reg_exp(vv); } else if (!strcmp(tt,"fontlist")) { ww=to_spc(vv); xx=skip_spc(ww); if (!(*vv)) lper(tedname,lno,"argument expected"); setFontList(vv); } else if (!strcmp(tt,"LoadKeyDefInto")) { int no; char mstr[16], *p; tt=parse_Cstr(tedname, lno,vv,&uu); if (!(*tt)) lper(tedname,lno,"file name expected"); ww=skip_spc(uu); if (!*ww) lper(tedname,lno,"Bind number expected"); no=*ww-'0'; if (no<=0 || no>=4) lper(tedname,lno,"Bind number must be less than 4 and greater than 0"); if ((p=strchr(tt,'.'))==NULL) { mode_str_m[no]=" "; } else { p++; if (! *p) mode_str_m[no]=strdup(" "); else mode_str_m[no]=strdup(p); } LoadTedrc(tt,0,no); } } fclose(fp); if (!depth) { kdefno=kdefno_m[kdefmapno]; qsort(kdef,kdefno,sizeof(kdef[0]),qcmp); bzero(hdef,sizeof(hdef)); bzero(kdefhash[kdefmapno],128*sizeof(int)); for(i=0;i<kdefno;i++) { j=KEYHASH(kdef[i].kcode[0]); if (hdef[j]) continue; hdef[j]=1; kdefhash[kdefmapno][j]=i; } kdefhash[kdefmapno][127]=kdefno; for(i=126;i>=0;i--) if (!hdef[i]) kdefhash[kdefmapno][i]=kdefhash[kdefmapno][i+1]; ReLoadTed=1; if (X_inited) alloc_pc_colors(); } return 0; }
/* * authtrust - declare a key to be trusted/untrusted */ void authtrust( keyid_t keyno, u_long trust ) { struct savekey *sk; /* * Search bin for key; if it does not exist and is untrusted, * forget it. */ sk = key_hash[KEYHASH(keyno)]; while (sk != 0) { if (keyno == sk->keyid) break; sk = sk->next; } if (sk == 0 && !trust) return; /* * There are two conditions remaining. Either it does not * exist and is to be trusted or it does exist and is or is * not to be trusted. */ if (sk != 0) { if (cache_keyid == keyno) { cache_flags = 0; cache_keyid = 0; } /* * Key exists. If it is to be trusted, say so and * update its lifetime. If not, return it to the * free list. */ if (trust > 0) { sk->flags |= KEY_TRUSTED; if (trust > 1) sk->lifetime = current_time + trust; else sk->lifetime = 0; return; } sk->flags &= ~KEY_TRUSTED; { struct savekey *skp; skp = key_hash[KEYHASH(keyno)]; if (skp == sk) { key_hash[KEYHASH(keyno)] = sk->next; } else { while (skp->next != sk) skp = skp->next; skp->next = sk->next; } authnumkeys--; sk->next = authfreekeys; authfreekeys = sk; authnumfreekeys++; } return; } /* * Here there is not key, but the key is to be trusted. There * seems to be a disconnect here. Here we allocate a new key, * but do not specify a key type, key or key length. */ if (authnumfreekeys == 0) if (auth_moremem() == 0) return; sk = authfreekeys; authfreekeys = sk->next; authnumfreekeys--; sk->keyid = keyno; sk->type = 0; sk->keylen = 0; sk->flags = KEY_TRUSTED; sk->next = key_hash[KEYHASH(keyno)]; key_hash[KEYHASH(keyno)] = sk; authnumkeys++; return; }
void MD5auth_setkey( keyid_t keyno, int keytype, const u_char *key, size_t len ) { struct savekey *sk; /* * See if we already have the key. If so just stick in the * new value. */ sk = key_hash[KEYHASH(keyno)]; while (sk != NULL) { if (keyno == sk->keyid) { sk->type = keytype; sk->keylen = min(len, sizeof(sk->k.MD5_key)); #ifndef DISABLE_BUG1243_FIX memcpy(sk->k.MD5_key, key, sk->keylen); #else strncpy((char *)sk->k.MD5_key, (const char *)key, sizeof(sk->k.MD5_key)); #endif if (cache_keyid == keyno) { cache_flags = 0; cache_keyid = 0; } return; } sk = sk->next; } /* * Need to allocate new structure. Do it. */ if (0 == authnumfreekeys && !auth_moremem()) return; sk = authfreekeys; authfreekeys = sk->next; authnumfreekeys--; sk->keyid = keyno; sk->type = keytype; sk->flags = 0; sk->lifetime = 0; sk->keylen = min(len, sizeof(sk->k.MD5_key)); #ifndef DISABLE_BUG1243_FIX memcpy(sk->k.MD5_key, key, sk->keylen); #else strncpy((char *)sk->k.MD5_key, (const char *)key, sizeof(sk->k.MD5_key)); #endif sk->next = key_hash[KEYHASH(keyno)]; key_hash[KEYHASH(keyno)] = sk; #ifdef DEBUG if (debug > 1) { char hex[] = "0123456789abcdef"; int j; printf("auth_setkey: key %d type %d len %d ", sk->keyid, sk->type, sk->keylen); for (j = 0; j < sk->keylen; j++) printf("%c%c", hex[key[j] >> 4], hex[key[j] & 0xf]); printf("\n"); }
/* * authtrust - declare a key to be trusted/untrusted */ void authtrust( keyid_t id, u_long trust ) { symkey ** bucket; symkey * sk; u_long lifetime; /* * Search bin for key; if it does not exist and is untrusted, * forget it. */ bucket = &key_hash[KEYHASH(id)]; for (sk = *bucket; sk != NULL; sk = sk->hlink) { if (id == sk->keyid) break; } if (!trust && NULL == sk) return; /* * There are two conditions remaining. Either it does not * exist and is to be trusted or it does exist and is or is * not to be trusted. */ if (sk != NULL) { if (cache_keyid == id) { cache_flags = 0; cache_keyid = 0; } /* * Key exists. If it is to be trusted, say so and * update its lifetime. */ if (trust > 0) { sk->flags |= KEY_TRUSTED; if (trust > 1) sk->lifetime = current_time + trust; else sk->lifetime = 0; return; } /* No longer trusted, return it to the free list. */ freesymkey(sk, bucket); return; } /* * keyid is not present, but the is to be trusted. We allocate * a new key, but do not specify a key type or secret. */ if (trust > 1) { lifetime = current_time + trust; } else { lifetime = 0; } allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL); }
/* 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 }