Example #1
0
static int kerberosv4_decode_packet(void *context,
				    const char *input, unsigned inputlen,
				    char **output, unsigned *outputlen)
{
    context_t *text = (context_t *) context;
    int result;
    MSG_DAT data;
    
    memset(&data,0,sizeof(MSG_DAT));
    
    KRB_LOCK_MUTEX(text->utils);
    
    if (text->sec_type == KRB_SEC_ENCRYPTION) {
	result=krb_rd_priv(input, inputlen, text->init_keysched, 
			   &text->session, &text->ip_remote,
			   &text->ip_local, &data);
    } else if (text->sec_type == KRB_SEC_INTEGRITY) {
        result = krb_rd_safe(input, inputlen,
			     &text->session, &text->ip_remote,
			     &text->ip_local, &data);
    } else {
        KRB_UNLOCK_MUTEX(text->utils);
	text->utils->seterror(text->utils->conn, 0,
			      "KERBEROS_4 decode called with KRB_SEC_NONE");
	return SASL_FAIL;
    }
    
    KRB_UNLOCK_MUTEX(text->utils);
    
    /* see if the krb library gave us a failure */
    if (result != 0) {
	text->utils->seterror(text->utils->conn, 0, get_krb_err_txt(result));
	return SASL_FAIL;
    }
    
    /* check to make sure the timestamps are ok */
    if ((data.time_sec < text->time_sec) || /* if an earlier time */
	(((data.time_sec == text->time_sec) && /* or the exact same time */
	  (data.time_5ms < text->time_5ms)))) 
	{
	    text->utils->seterror(text->utils->conn, 0, "timestamps not ok");
	    return SASL_FAIL;
	}
    
    text->time_sec = data.time_sec;
    text->time_5ms = data.time_5ms;
    
    result = _plug_buf_alloc(text->utils, &text->decode_once_buf,
			     &text->decode_once_buf_len,
			     data.app_length + 1);
    if(result != SASL_OK)
	return result;
    
    *output = text->decode_once_buf;
    *outputlen = data.app_length;
    memcpy(*output, data.app_data, data.app_length);
    (*output)[*outputlen] = '\0';
    
    return SASL_OK;
}
Example #2
0
static int
krb4_decode(void *app_data, void *buf, int len, int level,
            struct connectdata *conn)
{
    MSG_DAT m;
    int e;
    struct krb4_data *d = app_data;

    if(level == prot_safe)
        e = krb_rd_safe(buf, len, &d->key,
                        (struct sockaddr_in *)REMOTE_ADDR,
                        (struct sockaddr_in *)LOCAL_ADDR, &m);
    else
        e = krb_rd_priv(buf, len, d->schedule, &d->key,
                        (struct sockaddr_in *)REMOTE_ADDR,
                        (struct sockaddr_in *)LOCAL_ADDR, &m);
    if(e)
    {
        struct SessionHandle *data = conn->data;
        infof(data, "krb4_decode: %s\n", krb_get_err_text(e));
        return -1;
    }
    memmove(buf, m.app_data, m.app_length);
    return m.app_length;
}
Example #3
0
int krb_sendauth_udpchk(long options, LONG checksum, MSG_DAT *msg_data, 
	CREDENTIALS* cred, Key_schedule *schedule, struct sockaddr_in *laddr,
	struct sockaddr_in *faddr, LPSTR packet)
{                   
	int cc;
	long tkt_len;      
	u_long cksum;
	u_char priv_buf[1024];
	
	/* mutual authentication, if desired */
	if (options & KOPT_DO_MUTUAL) {
		/* get the length of the reply */
		bcopy(packet,(char*) &tkt_len, sizeof(tkt_len));
		tkt_len = ntohl((unsigned long) tkt_len);
		
		/* if the length is negative, the server failed to recognize us
		 */
		if ((tkt_len < 0) || (tkt_len > sizeof(priv_buf)))
			return (KFAILURE);      /* XXX */
		/* read the reply... */
		bcopy(packet+sizeof(tkt_len), (char *)priv_buf, 
			(int) tkt_len);
			
		/* ...and decrypt it */
#ifndef NOENCRYPTION
		key_sched(cred->session, *schedule);
#endif /* !NOENCRYPTION */
		if (cc = krb_rd_priv(priv_buf, (unsigned long) tkt_len, *schedule,
				cred->session, faddr, laddr, msg_data))
			return (cc);
				
		/* fetch the (modified) checksum */
		(void) bcopy((char *)msg_data->app_data, (char *)&cksum,
			sizeof(cksum));
		cksum = ntohl(cksum);
		
		/* if it doesn't match, fail */
		if (cksum != checksum + 1)
			return (KFAILURE);      /* XXX */
	}
	return (KSUCCESS);
}
Example #4
0
static int
krb4_decode(void *app_data, void *buf, int len, int level)
{
    MSG_DAT m;
    int e;
    struct krb4_data *d = app_data;
    
    if(level == prot_safe)
	e = krb_rd_safe(buf, len, &d->key,
			(struct sockaddr_in *)REMOTE_ADDR,
			(struct sockaddr_in *)LOCAL_ADDR, &m);
    else
	e = krb_rd_priv(buf, len, d->schedule, &d->key, 
			(struct sockaddr_in *)REMOTE_ADDR,
			(struct sockaddr_in *)LOCAL_ADDR, &m);
    if(e){
	ftp_err("krb4_decode: %s", krb_get_err_text(e));
	return -1;
    }
    memmove(buf, m.app_data, m.app_length);
    return m.app_length;
}
Example #5
0
static int decrypt_tkt(char *user, char *instance, char *realm, char *arg,
		       int (*key_proc)(char *, char *, char *,
				       char *, C_Block),
		       KTEXT *cipp)
{
    MSG_DAT msg_data;		/* Message data containing decrypted data */
    KTEXT_ST auth;		/* Authenticator */
    AUTH_DAT auth_dat;		/* Authentication data */
    KTEXT cip = *cipp;
    MSG_DAT scip;
    int status = 0;
    des_cblock key;
    des_key_schedule sched;
    char phost[MAXHOSTNAMELEN + 1];
    struct sockaddr_in caddr;	/* client internet address */
    struct sockaddr_in saddr;	/* server internet address */

    rkinitd_intkt_info *rii = (rkinitd_intkt_info *)arg;

    u_char enc_data[MAX_KTXT_LEN];

    SBCLEAR(auth);
    SBCLEAR(auth_dat);
    SBCLEAR(scip);
    BCLEAR(enc_data);

    scip.app_data = enc_data;

    /*
     * Exchange with the client our response from the KDC (ticket encrypted
     * in user's private key) for the same ticket encrypted in our
     * (not yet known) session key.
     */

    rpc_exchange_tkt(cip, &scip);

    /*
     * Get the authenticator
     */

    SBCLEAR(auth);

    rpc_getauth(&auth, &caddr, &saddr);

    /*
     * Decode authenticator and extract session key.  The first zero
     * means we don't care what host this comes from.  This needs to
     * be done with euid of root so that /etc/srvtab can be read.
     */

    BCLEAR(phost);
    this_phost(phost, sizeof(phost));

    /*
     * This function has to use longjmp to return to the caller
     * because the kerberos library routine that calls it doesn't
     * pay attention to the return value it gives.  That means that
     * if any of these routines failed, the error returned to the client
     * would be "password incorrect".
     */

    status = krb_rd_req(&auth, KEY, phost, caddr.sin_addr.s_addr,
			    &auth_dat, "");
    if (status) {
	sprintf(errbuf, "krb_rd_req: %s", krb_err_txt[status]);
	rkinit_errmsg(errbuf);
	longjmp(rii->env, status);
    }

    memcpy(key, auth_dat.session, sizeof(key));
    if (des_key_sched(key, sched)) {
	sprintf(errbuf, "Error in des_key_sched");
	rkinit_errmsg(errbuf);
	longjmp(rii->env, RKINIT_DES);
    }

    /* Decrypt the data. */
    if ((status =
	 krb_rd_priv((u_char *)scip.app_data, scip.app_length,
		     sched, key, &caddr, &saddr, &msg_data)) == KSUCCESS) {
	cip->length = msg_data.app_length;
	memcpy(cip->dat, msg_data.app_data, msg_data.app_length);
	cip->dat[cip->length] = 0;
    }
    else {
	sprintf(errbuf, "krb_rd_priv: %s", krb_err_txt[status]);
	rkinit_errmsg(errbuf);
	longjmp(rii->env, status);
    }
    if (setuid(user_id) < 0) {
	sprintf(errbuf,	"Failure setting uid to %lu: %s\n",
		(unsigned long)user_id, strerror(errno));
	rkinit_errmsg(errbuf);
	longjmp(rii->env, RKINIT_DAEMON);
    }
    return(KSUCCESS);
}
Example #6
0
static int
try_krb4_authentication(void)
{
	KTEXT_ST auth;		/* Kerberos data */
	char *reply;
	char inst[INST_SZ];
	char *realm;
	CREDENTIALS cred;
	int r, type;
	socklen_t slen;
	Key_schedule schedule;
	u_long checksum, cksum;
	MSG_DAT msg_data;
	struct sockaddr_in local, foreign;
	struct stat st;

	/* Don't do anything if we don't have any tickets. */
	if (stat(tkt_string(), &st) < 0)
		return 0;

	strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)),
	    INST_SZ);

	realm = (char *)krb_realmofhost(get_canonical_hostname(1));
	if (!realm) {
		debug("Kerberos v4: no realm for %s", get_canonical_hostname(1));
		return 0;
	}
	/* This can really be anything. */
	checksum = (u_long)getpid();

	r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);
	if (r != KSUCCESS) {
		debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]);
		return 0;
	}
	/* Get session key to decrypt the server's reply with. */
	r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred);
	if (r != KSUCCESS) {
		debug("get_cred failed: %s", krb_err_txt[r]);
		return 0;
	}
	des_key_sched((des_cblock *) cred.session, schedule);

	/* Send authentication info to server. */
	packet_start(SSH_CMSG_AUTH_KERBEROS);
	packet_put_string((char *) auth.dat, auth.length);
	packet_send();
	packet_write_wait();

	/* Zero the buffer. */
	(void) memset(auth.dat, 0, MAX_KTXT_LEN);

	slen = sizeof(local);
	memset(&local, 0, sizeof(local));
	if (getsockname(packet_get_connection_in(),
	    (struct sockaddr *)&local, &slen) < 0)
		debug("getsockname failed: %s", strerror(errno));

	slen = sizeof(foreign);
	memset(&foreign, 0, sizeof(foreign));
	if (getpeername(packet_get_connection_in(),
	    (struct sockaddr *)&foreign, &slen) < 0) {
		debug("getpeername failed: %s", strerror(errno));
		cleanup_exit(255);
	}
	/* Get server reply. */
	type = packet_read();
	switch (type) {
	case SSH_SMSG_FAILURE:
		/* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
		debug("Kerberos v4 authentication failed.");
		return 0;
		break;

	case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
		/* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
		debug("Kerberos v4 authentication accepted.");

		/* Get server's response. */
		reply = packet_get_string((u_int *) &auth.length);
		if (auth.length >= MAX_KTXT_LEN)
			fatal("Kerberos v4: Malformed response from server");
		memcpy(auth.dat, reply, auth.length);
		free(reply);

		packet_check_eom();

		/*
		 * If his response isn't properly encrypted with the session
		 * key, and the decrypted checksum fails to match, he's
		 * bogus. Bail out.
		 */
		r = krb_rd_priv(auth.dat, auth.length, (void *)schedule,
		    &cred.session, &foreign, &local, &msg_data);
		if (r != KSUCCESS) {
			debug("Kerberos v4 krb_rd_priv failed: %s",
			    krb_err_txt[r]);
			packet_disconnect("Kerberos v4 challenge failed!");
		}
		/* Fetch the (incremented) checksum that we supplied in the request. */
		memcpy((char *)&cksum, (char *)msg_data.app_data,
		    sizeof(cksum));
		cksum = ntohl(cksum);

		/* If it matches, we're golden. */
		if (cksum == checksum + 1) {
			debug("Kerberos v4 challenge successful.");
			return 1;
		} else
			packet_disconnect("Kerberos v4 challenge failed!");
		break;

	default:
		packet_disconnect("Protocol error on Kerberos v4 response: %d", type);
	}
	return 0;
}