예제 #1
0
파일: krb4.c 프로젝트: casualuser/yafc
static int
mk_auth(struct krb4_data *d, KTEXT adat, 
	char *service, char *host, int checksum)
{
    int ret;
    CREDENTIALS cred;
    char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];

    strlcpy(sname, service, sizeof(sname));
    strlcpy(inst, krb_get_phost(host), sizeof(inst));
    strlcpy(realm, krb_realmofhost(host), sizeof(realm));
    ret = krb_mk_req(adat, sname, inst, realm, checksum);
    if(ret)
	return ret;
    strlcpy(sname, service, sizeof(sname));
    strlcpy(inst, krb_get_phost(host), sizeof(inst));
    strlcpy(realm, krb_realmofhost(host), sizeof(realm));
    ret = krb_get_cred(sname, inst, realm, &cred);
    memmove(&d->key, &cred.session, sizeof(des_cblock));
    des_key_sched(&d->key, d->schedule);
    memset(&cred, 0, sizeof(cred));
    return ret;
}
예제 #2
0
파일: krb.c 프로젝트: mit-athena/rkinitd
static void this_phost(char *host, int hostlen)
{
    char this_host[MAXHOSTNAMELEN + 1];

    BCLEAR(this_host);

    if (gethostname(this_host, sizeof(this_host)) < 0) {
	sprintf(errbuf, "gethostname: %s", strerror(errno));
	rkinit_errmsg(errbuf);
	error();
	exit(1);
    }

    strncpy(host, krb_get_phost(this_host), hostlen - 1);
}
예제 #3
0
/*
 * 
 * K4_auth_send - gets authentication bits we need to send to KDC.
 * 
 * Result is left in auth
 *
 * Returns: 0 on failure, 1 on success
 */
static int
k4_auth_send(kstream ks)
{
  int r;                                      /* Return value */
  char instance[INST_SZ];
  char *realm;
  char buf[256];

  memset(instance, 0, sizeof(instance));

  if (realm = krb_get_phost(szHostName))
    lstrcpy(instance, realm);

  realm = krb_realmofhost(szHostName);

  if (!realm) {
    strcpy(buf, "Can't find realm for host \"");
    strncat(buf, szHostName, sizeof(buf) - 1 - strlen(buf));
    strncat(buf, "\"", sizeof(buf) - 1 - strlen(buf));
    auth_abort(ks, buf, 0);
    return KFAILURE;
  }

  r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0);

  if (r == 0)
    r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred);

  if (r) {
    strcpy(buf, "Can't get \"");
    strncat(buf, KRB_SERVICE_NAME, sizeof(buf) - 1 - strlen(buf));
    if (instance[0] != 0) {
      strncat(buf, ".", sizeof(buf) - 1 - strlen(buf));
      lstrcat(buf, instance);
    }
    strncat(buf, "@", sizeof(buf) - 1 - strlen(buf));
    lstrcat(buf, realm);
    strncat(buf, "\" ticket", sizeof(buf) - 1 - strlen(buf));
    auth_abort(ks, buf, r);

    return r;
  }

  if (!szUserName[0])			/* Copy if not there */
    strcpy(szUserName, cred.pname);

  return(1);
}
예제 #4
0
int krb_sendauth_udp(long options, int fd, KTEXT_FP ticket,
	const LPSTR service, const LPSTR inst, LPSTR realm, LONG checksum,
	MSG_DAT *msg_data, CREDENTIALS *cred, Key_schedule *schedule,
	struct sockaddr_in *laddr, struct sockaddr_in *faddr, LPSTR version,
	LPSTR buffer, int sz)
{
	int rem, i, cc;
	char srv_inst[INST_SZ];
	char krb_realm[REALM_SZ];
	char buf[BUFSIZ];
	long tkt_len;
	u_char priv_buf[1024];
	u_long cksum;
	
	rem = KSUCCESS;
	
	/* get current realm if not passed in */
	if (!realm) {
		rem = krb_get_lrealm(krb_realm,1);
		if (rem != KSUCCESS)
			return (rem);
		realm = krb_realm;
	}
	
	/* Copy instance into local storage, canonicalizing if desired */
	if (options & KOPT_DONT_CANON)
		(void) strncpy(srv_inst, inst, INST_SZ);
	else
		(void) strncpy((LPSTR)srv_inst, (LPSTR)krb_get_phost(inst), INST_SZ);
		
	/* Get the ticket if desired */
	if (!(options & KOPT_DONT_MK_REQ)) {
		rem = krb_mk_req(ticket, service, srv_inst, realm, checksum);
		if (rem != KSUCCESS)
			return (rem);
	}
	
#ifdef ATHENA_COMPAT
	/* this is only for compatibility with old servers */
	if (options & KOPT_DO_OLDSTYLE) {
		(void) sprintf(buf, "%d ", ticket->length);
		(void) write(fd, buf, strlen(buf));
		(void) write(fd, (char *) ticket->dat, ticket->length);
		return (rem);
	}
#endif /* ATHENA_COMPAT */
	/* if the mutual auth, get credentials so we have service session
	 * keys for decryption below
	 */
	if (options & KOPT_DO_MUTUAL)
	{
		/*if (cc == 1)
		 *{
		 *      krb_get_cred(service, srv_inst, realm, cred);
		 *      return (cc);
		 *}
		 */
		krb_get_cred(service, srv_inst, realm, cred);
	}
			
	/* Zero the buffer */
	(void) bzero(buf, BUFSIZ);
	
	/* insert version strings */
	(void) strncpy(buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN);
	
	/* increment past version strings */
	i = 2*KRB_SENDAUTH_VLEN;
	
	/* put ticket length into buffer */
	tkt_len = htonl((unsigned long) ticket->length);
	(void) bcopy((char *) &tkt_len, buf+i, ticket->length);
	i += ticket->length;
	
	/* Normally, we write the request to the server
	** For udp, esp. TechNotify type protocols, we
	** just return the buffer.  
	*/
	if (sz < i)
		return HEY_PAUL_WHAT_ERROR;     /* Buffer not big enough */
	bcopy(buf, buffer, i);
	return (KSUCCESS);
}
예제 #5
0
파일: kerberos.c 프로젝트: aunali1/exopc
static int
kerberos4_send(char *name, Authenticator *ap)
{
    KTEXT_ST auth;
    char instance[INST_SZ];
    char *realm;
    CREDENTIALS cred;
    int r;

    printf("[ Trying %s ... ]\r\n", name);
    if (!UserNameRequested) {
	if (auth_debug_mode) {
	    printf("Kerberos V4: no user name supplied\r\n");
	}
	return(0);
    }

    memset(instance, 0, sizeof(instance));

    if ((realm = krb_get_phost(RemoteHostName)))
	strncpy(instance, realm, sizeof(instance));

    instance[sizeof(instance)-1] = '\0';

    realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);

    if (!realm) {
	printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
	return(0);
    }
    r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0L);
    if (r) {
	printf("mk_req failed: %s\r\n", krb_get_err_text(r));
	return(0);
    }
    r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred);
    if (r) {
	printf("get_cred failed: %s\r\n", krb_get_err_text(r));
	return(0);
    }
    if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
	if (auth_debug_mode)
	    printf("Not enough room for user name\r\n");
	return(0);
    }
    if (auth_debug_mode)
	printf("Sent %d bytes of authentication data\r\n", auth.length);
    if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) {
	if (auth_debug_mode)
	    printf("Not enough room for authentication data\r\n");
	return(0);
    }
#ifdef ENCRYPTION
    /* create challenge */
    if ((ap->way & AUTH_HOW_MASK)==AUTH_HOW_MUTUAL) {
	int i;

	des_key_sched(&cred.session, sched);
	des_init_random_number_generator(&cred.session);
	des_new_random_key(&session_key);
	des_ecb_encrypt(&session_key, &session_key, sched, 0);
	des_ecb_encrypt(&session_key, &challenge, sched, 0);

	/*
	  old code
	  Some CERT Advisory thinks this is a bad thing...
	    
	  des_init_random_number_generator(&cred.session);
	  des_new_random_key(&challenge);
	  des_ecb_encrypt(&challenge, &session_key, sched, 1);
	  */
	  
	/*
	 * Increment the challenge by 1, and encrypt it for
	 * later comparison.
	 */
	for (i = 7; i >= 0; --i) 
	    if(++challenge[i] != 0) /* No carry! */
		break;
	des_ecb_encrypt(&challenge, &challenge, sched, 1);
    }

#endif

    if (auth_debug_mode) {
	printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
	printd(auth.dat, auth.length);
	printf("\r\n");
	printf("Sent Kerberos V4 credentials to server\r\n");
    }
    return(1);
}
예제 #6
0
/*
 * try krb4 authentication,
 * return 1 on success, 0 on failure, -1 if krb4 is not available
 */
int
auth_krb4_password(Authctxt *authctxt, const char *password)
{
	AUTH_DAT adata;
	KTEXT_ST tkt;
	struct hostent *hp;
	struct passwd *pw;
	char localhost[MAXHOSTNAMELEN], phost[INST_SZ], realm[REALM_SZ];
	u_int32_t faddr;
	int r;

	if ((pw = authctxt->pw) == NULL)
		return (0);

	/*
	 * Try Kerberos password authentication only for non-root
	 * users and only if Kerberos is installed.
	 */
	if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
		/* Set up our ticket file. */
		if (!krb4_init(authctxt)) {
			log("Couldn't initialize Kerberos ticket file for %s!",
			    pw->pw_name);
			goto failure;
		}
		/* Try to get TGT using our password. */
		r = krb_get_pw_in_tkt((char *) pw->pw_name, "", realm,
		    "krbtgt", realm, DEFAULT_TKT_LIFE, (char *)password);
		if (r != INTK_OK) {
			debug("Kerberos v4 password authentication for %s "
			    "failed: %s", pw->pw_name, krb_err_txt[r]);
			goto failure;
		}
		/* Successful authentication. */
		chown(tkt_string(), pw->pw_uid, pw->pw_gid);

		/*
		 * Now that we have a TGT, try to get a local
		 * "rcmd" ticket to ensure that we are not talking
		 * to a bogus Kerberos server.
		 */
		gethostname(localhost, sizeof(localhost));
		strlcpy(phost, (char *)krb_get_phost(localhost),
		    sizeof(phost));
		r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);

		if (r == KSUCCESS) {
			if ((hp = gethostbyname(localhost)) == NULL) {
				log("Couldn't get local host address!");
				goto failure;
			}
			memmove((void *)&faddr, (void *)hp->h_addr,
			    sizeof(faddr));

			/* Verify our "rcmd" ticket. */
			r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost,
			    faddr, &adata, "");
			if (r == RD_AP_UNDEC) {
				/*
				 * Probably didn't have a srvtab on
				 * localhost. Disallow login.
				 */
				log("Kerberos v4 TGT for %s unverifiable, "
				    "no srvtab installed? krb_rd_req: %s",
				    pw->pw_name, krb_err_txt[r]);
				goto failure;
			} else if (r != KSUCCESS) {
				log("Kerberos v4 %s ticket unverifiable: %s",
				    KRB4_SERVICE_NAME, krb_err_txt[r]);
				goto failure;
			}
		} else if (r == KDC_PR_UNKNOWN) {
			/*
			 * Disallow login if no rcmd service exists, and
			 * log the error.
			 */
			log("Kerberos v4 TGT for %s unverifiable: %s; %s.%s "
			    "not registered, or srvtab is wrong?", pw->pw_name,
			    krb_err_txt[r], KRB4_SERVICE_NAME, phost);
			goto failure;
		} else {
			/*
			 * TGT is bad, forget it. Possibly spoofed!
			 */
			debug("WARNING: Kerberos v4 TGT possibly spoofed "
			    "for %s: %s", pw->pw_name, krb_err_txt[r]);
			goto failure;
		}
		/* Authentication succeeded. */
		return (1);
	} else
		/* Logging in as root or no local Kerberos realm. */
		debug("Unable to authenticate to Kerberos.");

 failure:
	krb4_cleanup_proc(authctxt);

	if (!options.kerberos_or_local_passwd)
		return (0);

	/* Fall back to ordinary passwd authentication. */
	return (-1);
}
예제 #7
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;
}