kerberos.c

来自「经典的unix下telnetd代码」· C语言 代码 · 共 752 行 · 第 1/2 页

C
752
字号
	} else {	    char *msg;	    asprintf (&msg, "user `%s' is not authorized to "		      "login as `%s'", 		      krb_unparse_name_long(adat.pname, 					    adat.pinst, 					    adat.prealm), 		      UserNameRequested ? UserNameRequested : "<nobody>");	    if (msg == NULL)		Data(ap, KRB_REJECT, NULL, 0);	    else {		Data(ap, KRB_REJECT, (void *)msg, -1);		free(msg);	    }	    auth_finished(ap, AUTH_REJECT);	    break;	}	auth_finished(ap, AUTH_USER);	break;	    case KRB_CHALLENGE:#ifndef ENCRYPTION	Data(ap, KRB_RESPONSE, NULL, 0);#else	if(!VALIDKEY(session_key)){	    Data(ap, KRB_RESPONSE, NULL, 0);	    break;	}	des_key_sched(&session_key, sched);	{	    des_cblock d_block;	    int i;	    Session_Key skey;	    memmove(d_block, data, sizeof(d_block));	    /* make a session key for encryption */	    des_ecb_encrypt(&d_block, &session_key, sched, 1);	    skey.type=SK_DES;	    skey.length=8;	    skey.data=session_key;	    encrypt_session_key(&skey, 1);	    /* decrypt challenge, add one and encrypt it */	    des_ecb_encrypt(&d_block, &challenge, sched, 0);	    for (i = 7; i >= 0; i--)		if(++challenge[i] != 0)		    break;	    des_ecb_encrypt(&challenge, &challenge, sched, 1);	    Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge));	}#endif	break;    case KRB_FORWARD:	{	    des_key_schedule ks;	    unsigned char netcred[sizeof(CREDENTIALS)];	    CREDENTIALS cred;	    int ret;	    if(cnt > sizeof(cred))		abort();	    memcpy (session_key, adat.session, sizeof(session_key));	    des_set_key(&session_key, ks);	    des_pcbc_encrypt((void*)data, (void*)netcred, cnt, 			     ks, &session_key, DES_DECRYPT);	    unpack_cred(netcred, cnt, &cred);	    {		if(strcmp(cred.service, KRB_TICKET_GRANTING_TICKET) ||		   strncmp(cred.instance, cred.realm, sizeof(cred.instance)) ||		   cred.lifetime < 0 || cred.lifetime > 255 ||		   cred.kvno < 0 || cred.kvno > 255 ||		   cred.issue_date < 0 || 		   cred.issue_date > time(0) + CLOCK_SKEW ||		   strncmp(cred.pname, adat.pname, sizeof(cred.pname)) ||		   strncmp(cred.pinst, adat.pinst, sizeof(cred.pinst))){		    Data(ap, KRB_FORWARD_REJECT, "Bad credentials", -1);		}else{		    if((ret = tf_setup(&cred,				       cred.pname,				       cred.pinst)) == KSUCCESS){		        struct passwd *pw = getpwnam(UserNameRequested);			if (pw)			  chown(tkt_string(), pw->pw_uid, pw->pw_gid);			Data(ap, KRB_FORWARD_ACCEPT, 0, 0);		    } else{			Data(ap, KRB_FORWARD_REJECT, 			     krb_get_err_text(ret), -1);		    }		}	    }	    memset(data, 0, cnt);	    memset(ks, 0, sizeof(ks));	    memset(&cred, 0, sizeof(cred));	}		break;    default:	if (auth_debug_mode)	    printf("Unknown Kerberos option %d\r\n", data[-1]);	Data(ap, KRB_REJECT, 0, 0);	break;    }}voidkerberos4_reply(Authenticator *ap, unsigned char *data, int cnt){    Session_Key skey;    if (cnt-- < 1)	return;    switch (*data++) {    case KRB_REJECT:	if(auth_done){ /* XXX Ick! */	    printf("[ Kerberos V4 received unknown opcode ]\r\n");	}else{	    printf("[ Kerberos V4 refuses authentication ");	    if (cnt > 0) 		printf("because %.*s ", cnt, data);	    printf("]\r\n");	    auth_send_retry();	}	return;    case KRB_ACCEPT:	printf("[ Kerberos V4 accepts you ]\r\n");	auth_done = 1;	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {	    /*	     * Send over the encrypted challenge.	     */	    Data(ap, KRB_CHALLENGE, session_key, 		 sizeof(session_key));	    des_ecb_encrypt(&session_key, &session_key, sched, 1);	    skey.type = SK_DES;	    skey.length = 8;	    skey.data = session_key;	    encrypt_session_key(&skey, 0);#if 0	    kerberos4_forward(ap, &cred_session);#endif	    return;	}	auth_finished(ap, AUTH_USER);	return;    case KRB_RESPONSE:	/* make sure the response is correct */	if ((cnt != sizeof(des_cblock)) ||	    (memcmp(data, challenge, sizeof(challenge)))){	    printf("[ Kerberos V4 challenge failed!!! ]\r\n");	    auth_send_retry();	    return;	}	printf("[ Kerberos V4 challenge successful ]\r\n");	auth_finished(ap, AUTH_USER);	break;    case KRB_FORWARD_ACCEPT:	printf("[ Kerberos V4 accepted forwarded credentials ]\r\n");	break;    case KRB_FORWARD_REJECT:	printf("[ Kerberos V4 rejected forwarded credentials: `%.*s']\r\n",	       cnt, data);	break;    default:	if (auth_debug_mode)	    printf("Unknown Kerberos option %d\r\n", data[-1]);	return;    }}intkerberos4_status(Authenticator *ap, char *name, size_t name_sz, int level){    if (level < AUTH_USER)	return(level);    if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {	strlcpy(name, UserNameRequested, name_sz);	return(AUTH_VALID);    } else	return(AUTH_USER);}#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}voidkerberos4_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen){    int i;    buf[buflen-1] = '\0';		/* make sure its NULL terminated */    buflen -= 1;    switch(data[3]) {    case KRB_REJECT:		/* Rejected (reason might follow) */	strlcpy((char *)buf, " REJECT ", buflen);	goto common;    case KRB_ACCEPT:		/* Accepted (name might follow) */	strlcpy((char *)buf, " ACCEPT ", buflen);    common:	BUMP(buf, buflen);	if (cnt <= 4)	    break;	ADDC(buf, buflen, '"');	for (i = 4; i < cnt; i++)	    ADDC(buf, buflen, data[i]);	ADDC(buf, buflen, '"');	ADDC(buf, buflen, '\0');	break;    case KRB_AUTH:			/* Authentication data follows */	strlcpy((char *)buf, " AUTH", buflen);	goto common2;    case KRB_CHALLENGE:	strlcpy((char *)buf, " CHALLENGE", buflen);	goto common2;    case KRB_RESPONSE:	strlcpy((char *)buf, " RESPONSE", buflen);	goto common2;    default:	snprintf(buf, buflen, " %d (unknown)", data[3]);    common2:	BUMP(buf, buflen);	for (i = 4; i < cnt; i++) {	    snprintf(buf, buflen, " %d", data[i]);	    BUMP(buf, buflen);	}	break;    }}intkerberos4_cksum(unsigned char *d, int n){    int ck = 0;    /*     * A comment is probably needed here for those not     * well versed in the "C" language.  Yes, this is     * supposed to be a "switch" with the body of the     * "switch" being a "while" statement.  The whole     * purpose of the switch is to allow us to jump into     * the middle of the while() loop, and then not have     * to do any more switch()s.     *     * Some compilers will spit out a warning message     * about the loop not being entered at the top.     */    switch (n&03)	while (n > 0) {	case 0:	    ck ^= (int)*d++ << 24;	    --n;	case 3:	    ck ^= (int)*d++ << 16;	    --n;	case 2:	    ck ^= (int)*d++ << 8;	    --n;	case 1:	    ck ^= (int)*d++;	    --n;	}    return(ck);}static intpack_cred(CREDENTIALS *cred, unsigned char *buf){    unsigned char *p = buf;        memcpy (p, cred->service, ANAME_SZ);    p += ANAME_SZ;    memcpy (p, cred->instance, INST_SZ);    p += INST_SZ;    memcpy (p, cred->realm, REALM_SZ);    p += REALM_SZ;    memcpy(p, cred->session, 8);    p += 8;    p += krb_put_int(cred->lifetime, p, 4, 4);    p += krb_put_int(cred->kvno, p, 4, 4);    p += krb_put_int(cred->ticket_st.length, p, 4, 4);    memcpy(p, cred->ticket_st.dat, cred->ticket_st.length);    p += cred->ticket_st.length;    p += krb_put_int(0, p, 4, 4);    p += krb_put_int(cred->issue_date, p, 4, 4);    memcpy (p, cred->pname, ANAME_SZ);    p += ANAME_SZ;    memcpy (p, cred->pinst, INST_SZ);    p += INST_SZ;    return p - buf;}static intunpack_cred(unsigned char *buf, int len, CREDENTIALS *cred){    unsigned char *p = buf;    u_int32_t tmp;    strncpy (cred->service, p, ANAME_SZ);    cred->service[ANAME_SZ - 1] = '\0';    p += ANAME_SZ;    strncpy (cred->instance, p, INST_SZ);    cred->instance[INST_SZ - 1] = '\0';    p += INST_SZ;    strncpy (cred->realm, p, REALM_SZ);    cred->realm[REALM_SZ - 1] = '\0';    p += REALM_SZ;    memcpy(cred->session, p, 8);    p += 8;    p += krb_get_int(p, &tmp, 4, 0);    cred->lifetime = tmp;    p += krb_get_int(p, &tmp, 4, 0);    cred->kvno = tmp;    p += krb_get_int(p, &cred->ticket_st.length, 4, 0);    memcpy(cred->ticket_st.dat, p, cred->ticket_st.length);    p += cred->ticket_st.length;    p += krb_get_int(p, &tmp, 4, 0);    cred->ticket_st.mbz = 0;    p += krb_get_int(p, (u_int32_t *)&cred->issue_date, 4, 0);    strncpy (cred->pname, p, ANAME_SZ);    cred->pname[ANAME_SZ - 1] = '\0';    p += ANAME_SZ;    strncpy (cred->pinst, p, INST_SZ);    cred->pinst[INST_SZ - 1] = '\0';    p += INST_SZ;    return 0;}intkerberos4_forward(Authenticator *ap, void *v){    des_cblock *key = (des_cblock *)v;    CREDENTIALS cred;    char *realm;    des_key_schedule ks;    int len;    unsigned char netcred[sizeof(CREDENTIALS)];    int ret;    realm = krb_realmofhost(RemoteHostName);    if(realm == NULL)	return -1;    memset(&cred, 0, sizeof(cred));    ret = krb_get_cred(KRB_TICKET_GRANTING_TICKET,		       realm,		       realm, 		       &cred);    if(ret)	return ret;    des_set_key(key, ks);    len = pack_cred(&cred, netcred);    des_pcbc_encrypt((void*)netcred, (void*)netcred, len,		     ks, key, DES_ENCRYPT);    memset(ks, 0, sizeof(ks));    Data(ap, KRB_FORWARD, netcred, len);    memset(netcred, 0, sizeof(netcred));    return 0;}#endif /* KRB4 */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?