Пример #1
0
void
kerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
{
    struct sockaddr_in addr;
    char realm[REALM_SZ];
    char instance[INST_SZ];
    int r;
    int addr_len;

    if (cnt-- < 1)
	return;
    switch (*data++) {
    case KRB_AUTH:
	if (krb_get_lrealm(realm, 1) != KSUCCESS) {
	    Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("No local realm\r\n");
	    return;
	}
	memmove(auth.dat, data, auth.length = cnt);
	if (auth_debug_mode) {
	    printf("Got %d bytes of authentication data\r\n", cnt);
	    printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
	    printd(auth.dat, auth.length);
	    printf("\r\n");
	}
	k_getsockinst(0, instance, sizeof(instance));
	addr_len = sizeof(addr);
	if(getpeername(0, (struct sockaddr *)&addr, &addr_len) < 0) {
	    if(auth_debug_mode)
		printf("getpeername failed\r\n");
	    Data(ap, KRB_REJECT, "getpeername failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    return;
	}
	r = krb_rd_req(&auth, KRB_SERVICE_NAME,
		       instance, addr.sin_addr.s_addr, &adat, "");
	if (r) {
	    if (auth_debug_mode)
		printf("Kerberos failed him as %s\r\n", name);
	    Data(ap, KRB_REJECT, (void *)krb_get_err_text(r), -1);
	    auth_finished(ap, AUTH_REJECT);
	    return;
	}
	/* save the session key */
	memmove(session_key, adat.session, sizeof(adat.session));
	krb_kntoln(&adat, name);

	if (UserNameRequested && !kuserok(&adat, UserNameRequested)){
	    char ts[MAXPATHLEN];
	    struct passwd *pw = getpwnam(UserNameRequested);

	    if(pw){
		snprintf(ts, sizeof(ts),
			 "%s%u",
			 TKT_ROOT,
			 (unsigned)pw->pw_uid);
		setenv("KRBTKFILE", ts, 1);
	    }
	    Data(ap, KRB_ACCEPT, NULL, 0);
	} 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_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();

	    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.pname))){
		    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;
    }
}
Пример #2
0
int
listener::auth(int client_sock, 
	uid_t 		*uid_out, 
	gid_t 		*gid_out, 
	char 		*complete_name, int namelen
#ifdef USE_KRB
	,
	unsigned long ttime, // time ticket issued
	C_Block		*sessionkey
#endif
)
{
	FUNC(listener::auth);
	c_uid_t 			uid;
	int				remoteness=::same_process;


#ifdef DEBUG
	dumpaddrs(client_sock, "listener::run");
#endif
	(void) max_sock_opt(client_sock, SO_RCVBUF);

	get_remoteness(client_sock, remoteness);

#ifdef USE_KRB
	{
	// KERBEROS AUTHENTICATION
	/* specific to RPC 4.0 */ /* grot */
	int             krb_status;
	KTEXT_ST        ticket;
	AUTH_DAT        auth_data;
	char			version[20];
	Key_schedule    sched;
	INSTANCE		inst;
	struct sockaddr_in peer, me;

	// instance = '*' means authenticator will fill it in.
	memset(inst, '\0', sizeof(inst)); 
	inst[0] = '*';

#	ifdef MUTUAL
#	define kopt	KOPT_DO_MUTUAL
#	else
#	define kopt	0
#	endif

	krb_status = krb_recvauth(kopt, client_sock,
		&ticket, "rcmd", inst, &peer, &me, &auth_data,
		"" /* use /etc/srvtab */,  sched, version);

	if(krb_status != KSUCCESS) {
		ShoreVasLayer.client_service->log->log(log_error, 
		 "Kerberos error %s ", (char *)krb_err_txt[krb_status]);
		return ::error_remoteness;
	}

	// who's it from?
	uid = (c_uid_t) SVAS_OK;

	if (krb_kntoln(&auth_data, complete_name) != KSUCCESS) {
		strcpy(complete_name, "*No local name returned by krb_kntoln*");
		ShoreVasLayer.client_service->log->log(log_error, 
		 "Kerberos error %s ", (char *)krb_err_txt[krb_status]);
		return ::error_remoteness;
	}

#	ifdef DEBUG
	// print the info filled in by krb
	DBG(
		<< "KRB connect: version " << version  << "client krb-connect OK"
	)
#	endif 

	dassert(strcmp(auth_data.pname,complete_name)==0);
	}
	ttime = auth_data.time_sec, 
	*sessionkey = auth_data.session;
#else
	// NO KERBEROS: just read name and return uid
	{
		int cc; 

		if( (cc = ::read(client_sock, complete_name, namelen)) <0) {
			// TODO: Shouldn't this use log instead of perror?
			perror("read login complete_name");
			return ::error_remoteness;
		}
		complete_name[cc]='\0';
	}
#endif /* NO KERBEROS */

	{
		*uid_out = uid = uname2uid(complete_name, gid_out);
		if(uid==BAD_UID) {
			DBG(<<"NO SUCH USER!");
			ShoreVasLayer.client_service->
				log->log(log_error, "Authentication error: no such user: %s", complete_name);
			
			return ::error_remoteness;
		}
	}