Exemplo n.º 1
0
int
kerberos5_is_forward (TN_Authenticator * ap, unsigned char *data, int cnt,
		      char *errbuf, int errbuflen)
{
  int r = 0;
  krb5_data inbuf;

  inbuf.length = cnt;
  inbuf.data = (char *) data;
  if ((r = krb5_auth_con_genaddrs (telnet_context, auth_context,
				   net,
				   KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))
      || (r = rd_and_store_for_creds (telnet_context, auth_context,
				      &inbuf, ticket)))
    {
      snprintf (errbuf, errbuflen, "Read forwarded creds failed: %s",
		error_message (r));
      Data (ap, KRB_FORWARD_REJECT, errbuf, -1);
      DEBUG (("Could not read forwarded credentials\r\n"));
    }
  else
    {
      Data (ap, KRB_FORWARD_ACCEPT, 0, 0);
      DEBUG (("Forwarded credentials obtained\r\n"));
    }
  return r;
}
Exemplo n.º 2
0
void
kerberos5_forward(kstream ks)
{
    krb5_error_code r;
    krb5_ccache ccache;
    krb5_principal client = 0;
    krb5_principal server = 0;
    krb5_data forw_creds;

    forw_creds.data = 0;

    if ((r = krb5_cc_default(k5_context, &ccache))) {
      com_err(NULL, r, "Kerberos V5: could not get default ccache");
      return;
    }

    if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) {
      com_err(NULL, r, "Kerberos V5: could not get default principal");
      goto cleanup;
    }

    if ((r = krb5_sname_to_principal(k5_context, szHostName, KRB_SERVICE_NAME,
				     KRB5_NT_SRV_HST, &server))) {
      com_err(NULL, r, "Kerberos V5: could not make server principal");
      goto cleanup;
    }

    if ((r = krb5_auth_con_genaddrs(k5_context, auth_context, ks->fd,
			    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR))) {
      com_err(NULL, r, "Kerberos V5: could not gen local full address");
      goto cleanup;
    }

    if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client, server,
			        ccache, forwardable_flag, &forw_creds)) {
      com_err(NULL, r, "Kerberos V5: error getting forwarded creds");
      goto cleanup;
    }
    
    /* Send forwarded credentials */
    if (!Data(ks, KRB_FORWARD, forw_creds.data, forw_creds.length)) {
      MessageBox(HWND_DESKTOP,
		 "Not enough room for authentication data", "",
		 MB_OK | MB_ICONEXCLAMATION);
    }
    
cleanup:
    if (client)
      krb5_free_principal(k5_context, client);
    if (server)
      krb5_free_principal(k5_context, server);
#if 0 /* XXX */
	if (forw_creds.data)
      free(forw_creds.data);
#endif
    krb5_cc_close(k5_context, ccache);
}
Exemplo n.º 3
0
//----------------------------------------------------------------------
// Initialze some general structures for kerberos
//----------------------------------------------------------------------
int Condor_Auth_Kerberos :: init_kerberos_context()
{
    krb5_error_code code = 0;
    krb5_address  ** localAddr  = NULL;
    krb5_address  ** remoteAddr = NULL;

    // kerberos context_
    if (krb_context_ == NULL) {
        if ((code = krb5_init_context(&krb_context_))) {
            goto error;
        }
    }

    if ((code = krb5_auth_con_init(krb_context_, &auth_context_))) {
        goto error;
    }

    if ((code = krb5_auth_con_setflags(krb_context_, 
                                      auth_context_, 
                                      KRB5_AUTH_CONTEXT_DO_SEQUENCE))) {
        goto error;
    }
        
    if ((code = krb5_auth_con_genaddrs(krb_context_, 
                                      auth_context_, 
                                      mySock_->get_file_desc(),
                                      KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR|
                                      KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR
                                      ))) {
        goto error;
    }

    if ((code = krb5_auth_con_getaddrs(krb_context_, 
                                      auth_context_,
                                      localAddr, 
                                      remoteAddr))) {
        goto error;
    }

    // stash location
    defaultStash_ = param(STR_CONDOR_CACHE_DIR);

    if (defaultStash_ == NULL) {
        defaultStash_ = strdup(STR_DEFAULT_CONDOR_SPOOL);
    }
    
    return TRUE;
 error:
    dprintf( D_ALWAYS, "Unable to initialize kerberos: %s\n",
			 error_message(code) );
    return FALSE;
}
Exemplo n.º 4
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_auth_con_setaddrs_from_fd (krb5_context context,
				krb5_auth_context auth_context,
				void *p_fd)
{
    krb5_socket_t fd = *(krb5_socket_t *)p_fd;
    int flags = 0;
    if(auth_context->local_address == NULL)
	flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR;
    if(auth_context->remote_address == NULL)
	flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR;
    return krb5_auth_con_genaddrs(context, auth_context, fd, flags);
}
Exemplo n.º 5
0
int
do_krb5_login (int infd, struct auth_data *ap, const char **err_msg)
{
  krb5_auth_context auth_ctx = NULL;
  krb5_error_code status;
  krb5_data inbuf;
  krb5_data version;
  krb5_authenticator *authenticator;
  krb5_rcache rcache;
  krb5_keyblock *key;
  krb5_ticket *ticket;
  struct sockaddr_in laddr;
  int len;
  struct passwd *pwd;
  char *name;

  if (status = krb5_init_context (&ap->context))
    {
      syslog (LOG_ERR, "Error initializing krb5: %s", error_message (status));
      return status;
    }

  if ((status = krb5_auth_con_init (ap->context, &auth_ctx))
      || (status = krb5_auth_con_genaddrs (ap->context, auth_ctx, infd,
					   KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))
      || (status = krb5_auth_con_getrcache (ap->context, auth_ctx, &rcache)))
    return status;

  if (!rcache)
    {
      krb5_principal server;

      status = krb5_sname_to_principal (ap->context, 0, 0, KRB5_NT_SRV_HST,
					&server);
      if (status)
	return status;

      status = krb5_get_server_rcache (ap->context,
				       krb5_princ_component (ap->context,
							     server, 0),
				       &rcache);
      krb5_free_principal (ap->context, server);

      if (status)
	return status;

      status = krb5_auth_con_setrcache (ap->context, auth_ctx, rcache);
      if (status)
	return status;
    }

  len = sizeof (laddr);
  if (getsockname (infd, (struct sockaddr *) &laddr, &len))
    return errno;

  status = krb5_recvauth (ap->context, &auth_ctx, &infd, NULL, 0,
			  0, ap->keytab, &ticket);
  if (status)
    return status;

  if ((status = krb5_auth_con_getauthenticator (ap->context, auth_ctx,
						&authenticator)))
    return status;

  getstr (infd, &ap->lusername, NULL);
  getstr (infd, &ap->term, "TERM=");

  pwd = getpwnam (ap->lusername);
  if (pwd == NULL)
    {
      *err_msg = "getpwnam failed";
      syslog (LOG_ERR, "getpwnam failed: %m");
      return 1;
    }

  getstr (infd, &ap->rusername, NULL);

  if ((status = krb5_copy_principal (ap->context,
				     ticket->enc_part2->client, &ap->client)))
    return status;

  /*OK:: */
  if (ap->client && !krb5_kuserok (ap->context, ap->client, ap->lusername))
    return 1;

  krb5_unparse_name (ap->context, ap->client, &name);

  syslog (LOG_INFO | LOG_AUTH,
	  "%sKerberos V login from %s on %s\n",
	  (pwd->pw_uid == 0) ? "ROOT " : "", name, ap->hostname);
  free (name);

  return 0;
}
Exemplo n.º 6
0
static krb5_error_code
change_password_loop (krb5_context	context,
		      krb5_creds	*creds,
		      krb5_principal	targprinc,
		      char		*newpw,
		      int		*result_code,
		      krb5_data		*result_code_string,
		      krb5_data		*result_string,
		      struct kpwd_proc	*proc)
{
    krb5_error_code ret;
    krb5_auth_context auth_context = NULL;
    krb5_krbhst_handle handle = NULL;
    krb5_krbhst_info *hi;
    int sock;
    int i;
    int done = 0;
    krb5_realm realm = creds->client->realm;

    ret = krb5_auth_con_init (context, &auth_context);
    if (ret)
	return ret;

    krb5_auth_con_setflags (context, auth_context,
			    KRB5_AUTH_CONTEXT_DO_SEQUENCE);

    ret = krb5_krbhst_init (context, realm, KRB5_KRBHST_CHANGEPW, &handle);
    if (ret)
	goto out;

    while (!done && (ret = krb5_krbhst_next(context, handle, &hi)) == 0) {
	struct addrinfo *ai, *a;
	int is_stream;

	switch (hi->proto) {
	case KRB5_KRBHST_UDP:
	    if ((proc->flags & SUPPORT_UDP) == 0)
		continue;
	    is_stream = 0;
	    break;
	case KRB5_KRBHST_TCP:
	    if ((proc->flags & SUPPORT_TCP) == 0)
		continue;
	    is_stream = 1;
	    break;
	default:
	    continue;
	}

	ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
	if (ret)
	    continue;

	for (a = ai; !done && a != NULL; a = a->ai_next) {
	    int replied = 0;

	    sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
	    if (sock < 0)
		continue;

	    ret = connect(sock, a->ai_addr, a->ai_addrlen);
	    if (ret < 0) {
		close (sock);
		goto out;
	    }

	    ret = krb5_auth_con_genaddrs (context, auth_context, sock,
					  KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR);
	    if (ret) {
		close (sock);
		goto out;
	    }

	    for (i = 0; !done && i < 5; ++i) {
		fd_set fdset;
		struct timeval tv;

		if (!replied) {
		    replied = 0;
		    
		    ret = (*proc->send_req) (context,
					     &auth_context,
					     creds,
					     targprinc,
					     is_stream,
					     sock,
					     newpw,
					     hi->hostname);
		    if (ret) {
			close(sock);
			goto out;
		    }
		}
	    
		if (sock >= FD_SETSIZE) {
		    krb5_set_error_string(context, "fd %d too large", sock);
		    ret = ERANGE;
		    close (sock);
		    goto out;
		}

		FD_ZERO(&fdset);
		FD_SET(sock, &fdset);
		tv.tv_usec = 0;
		tv.tv_sec  = 1 + (1 << i);

		ret = select (sock + 1, &fdset, NULL, NULL, &tv);
		if (ret < 0 && errno != EINTR) {
		    close(sock);
		    goto out;
		}
		if (ret == 1) {
		    ret = (*proc->process_rep) (context,
						auth_context,
						is_stream,
						sock,
						result_code,
						result_code_string,
						result_string,
						hi->hostname);
		    if (ret == 0)
			done = 1;
		    else if (i > 0 && ret == KRB5KRB_AP_ERR_MUT_FAIL)
			replied = 1;
		} else {
		    ret = KRB5_KDC_UNREACH;
		}
	    }
	    close (sock);
	}
    }

 out:
    krb5_krbhst_free (context, handle);
    krb5_auth_con_free (context, auth_context);
    if (done)
	return 0;
    else {
	if (ret == KRB5_KDC_UNREACH) {
	    krb5_set_error_string(context,
				  "unable to reach any changepw server "
				  " in realm %s", realm);
	    *result_code = KRB5_KPASSWD_HARDERROR;
	}
	return ret;
    }
}
Exemplo n.º 7
0
static krb5_error_code
recvauth(int f,
	krb5_context krb_context,
	unsigned int *valid_checksum,
	krb5_ticket **ticket,
	int *auth_type,
	krb5_principal *client,
	int encr_flag,
	krb5_keytab keytab)
{
	krb5_error_code status = 0;
	krb5_auth_context auth_context = NULL;
	krb5_rcache rcache;
	krb5_authenticator *authenticator;
	krb5_data inbuf;
	krb5_data auth_version;

	*valid_checksum = 0;

	if ((status = krb5_auth_con_init(krb_context, &auth_context)))
		return (status);

	/* Only need remote address for rd_cred() to verify client */
	if ((status = krb5_auth_con_genaddrs(krb_context, auth_context, f,
			KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)))
		return (status);

	status = krb5_auth_con_getrcache(krb_context, auth_context, &rcache);
	if (status)
		return (status);

	if (!rcache) {
		krb5_principal server;

		status = krb5_sname_to_principal(krb_context, 0, 0,
						KRB5_NT_SRV_HST, &server);
		if (status)
			return (status);

		status = krb5_get_server_rcache(krb_context,
				krb5_princ_component(krb_context, server, 0),
				&rcache);
		krb5_free_principal(krb_context, server);
		if (status)
			return (status);

		status = krb5_auth_con_setrcache(krb_context, auth_context,
						rcache);
		if (status)
			return (status);
	}
	if ((status = krb5_compat_recvauth(krb_context,
					&auth_context,
					&f,
					NULL,	/* Specify daemon principal */
					0,	/* no flags */
					keytab,	/* NULL to use v5srvtab */
					ticket,	/* return ticket */
					auth_type, /* authentication system */
					&auth_version))) {
		if (*auth_type == KRB5_RECVAUTH_V5) {
			/*
			 * clean up before exiting
			 */
			getstr(f, rusername, sizeof (rusername), "remuser");
			getstr(f, lusername, sizeof (lusername), "locuser");
			getstr(f, term, sizeof (term), "Terminal type");
		}
		return (status);
	}

	getstr(f, lusername, sizeof (lusername), "locuser");
	getstr(f, term, sizeof (term), "Terminal type");

	kcmd_protocol = KCMD_UNKNOWN_PROTOCOL;
	if (auth_version.length != 9 || auth_version.data == NULL) {
		syslog(LOG_ERR, "Bad application protocol version length in "
		    "KRB5 exchange, exiting");
		fatal(f, "Bad application version length, exiting.");
	}
	/*
	 * Determine which Kerberos CMD protocol was used.
	 */
	if (strncmp(auth_version.data, "KCMDV0.1", 9) == 0) {
		kcmd_protocol = KCMD_OLD_PROTOCOL;
	} else if (strncmp(auth_version.data, "KCMDV0.2", 9) == 0) {
		kcmd_protocol = KCMD_NEW_PROTOCOL;
	} else {
		syslog(LOG_ERR, "Unrecognized KCMD protocol (%s), exiting",
			(char *)auth_version.data);
		fatal(f, "Unrecognized KCMD protocol, exiting");
	}

	if ((*auth_type == KRB5_RECVAUTH_V5) && chksum_flag &&
		kcmd_protocol == KCMD_OLD_PROTOCOL) {
		if ((status = krb5_auth_con_getauthenticator(krb_context,
							    auth_context,
							    &authenticator)))
			return (status);
		if (authenticator->checksum) {
			struct sockaddr_storage adr;
			int adr_length = sizeof (adr);
			int buflen;
			krb5_data input;
			krb5_keyblock key;
			char *chksumbuf;

			/*
			 * Define the lenght of the chksum buffer.
			 * chksum string = "[portnum]:termstr:username"
			 * The extra 32 is to hold a integer string for
			 * the portnumber.
			 */
			buflen = strlen(term) + strlen(lusername) + 32;
			chksumbuf = (char *)malloc(buflen);
			if (chksumbuf == 0) {
				krb5_free_authenticator(krb_context,
							authenticator);
				fatal(f, "Out of memory error");
			}

			if (getsockname(f, (struct sockaddr *)&adr,
							&adr_length) != 0) {
				krb5_free_authenticator(krb_context,
							authenticator);
				fatal(f, "getsockname error");
			}

			(void) snprintf(chksumbuf, buflen,
					"%u:%s%s",
					ntohs(SOCK_PORT(adr)),
					term, lusername);

			input.data = chksumbuf;
			input.length = strlen(chksumbuf);
			key.contents = (*ticket)->enc_part2->session->contents;
			key.length = (*ticket)->enc_part2->session->length;
			status = krb5_c_verify_checksum(krb_context,
						&key, 0,
						&input,
						authenticator->checksum,
						valid_checksum);

			if (status == 0 && *valid_checksum == 0)
				status = KRB5KRB_AP_ERR_BAD_INTEGRITY;

			if (chksumbuf)
				krb5_xfree(chksumbuf);
			if (status) {
				krb5_free_authenticator(krb_context,
							authenticator);
				return (status);
			}
		}
		krb5_free_authenticator(krb_context, authenticator);
	}

	if ((status = krb5_copy_principal(krb_context,
					(*ticket)->enc_part2->client,
					client)))
		return (status);

	/* Get the Unix username of the remote user */
	getstr(f, rusername, sizeof (rusername), "remuser");

	/* Get the Kerberos principal name string of the remote user */
	if ((status = krb5_unparse_name(krb_context, *client, &krusername)))
		return (status);

#ifdef DEBUG
	syslog(LOG_DEBUG | LOG_AUTH, "rlogind: got krb5 credentials for %s",
	    (krusername != NULL ? krusername : "******"));
#endif

	if (encr_flag) {
		status = krb5_auth_con_getremotesubkey(krb_context,
						    auth_context,
						    &session_key);
		if (status) {
			syslog(LOG_ERR, "Error getting KRB5 session "
			    "subkey, exiting");
			fatal(f, "Error getting KRB5 session subkey, exiting");
		}
		/*
		 * The "new" protocol requires that a subkey be sent.
		 */
		if (session_key == NULL &&
		    kcmd_protocol == KCMD_NEW_PROTOCOL) {
			syslog(LOG_ERR, "No KRB5 session subkey sent, exiting");
			fatal(f, "No KRB5 session subkey sent, exiting");
		}
		/*
		 * The "old" protocol does not permit an authenticator subkey.
		 * The key is taken from the ticket instead (see below).
		 */
		if (session_key != NULL &&
		    kcmd_protocol == KCMD_OLD_PROTOCOL) {
			syslog(LOG_ERR, "KRB5 session subkey not permitted "
			    "with old KCMD protocol, exiting");

			fatal(f, "KRB5 session subkey not permitted "
			    "with old KCMD protocol, exiting");
		}
		/*
		 * If no key at this point, use the session key from
		 * the ticket.
		 */
		if (session_key == NULL) {
			/*
			 * Save the session key so we can configure the crypto
			 * module later.
			 */
			status = krb5_copy_keyblock(krb_context,
					    (*ticket)->enc_part2->session,
					    &session_key);
			if (status) {
				syslog(LOG_ERR, "krb5_copy_keyblock failed");
				fatal(f, "krb5_copy_keyblock failed");
			}
		}
		/*
		 * If session key still cannot be found, we must
		 * exit because encryption is required here
		 * when encr_flag (-x) is set.
		 */
		if (session_key == NULL) {
			syslog(LOG_ERR, "Could not find an encryption key,"
				    "exiting");
			fatal(f, "Encryption required but key not found, "
			    "exiting");
		}
	}
	/*
	 * Use krb5_read_message to read the principal stuff.
	 */
	if ((status = krb5_read_message(krb_context, (krb5_pointer)&f,
					&inbuf)))
		fatal(f, "Error reading krb5 message");

	if (inbuf.length) { /* Forwarding being done, read creds */
		krb5_creds **creds = NULL;

		if (status = krb5_rd_cred(krb_context, auth_context, &inbuf,
					    &creds, NULL)) {
			if (rcache)
				(void) krb5_rc_close(krb_context, rcache);
			krb5_free_creds(krb_context, *creds);
			fatal(f, "Can't get forwarded credentials");
		}

		/* Store the forwarded creds in the ccache */
		if (status = store_forw_creds(krb_context,
					    creds, *ticket, lusername,
					    &ccache)) {
			if (rcache)
				(void) krb5_rc_close(krb_context, rcache);
			krb5_free_creds(krb_context, *creds);
			fatal(f, "Can't store forwarded credentials");
		}
		krb5_free_creds(krb_context, *creds);
	}

	if (rcache)
		(void) krb5_rc_close(krb_context, rcache);

	return (status);
}
Exemplo n.º 8
0
static krb5_error_code
chgpw_prexmit(krb5_context context, int proto,
              void *ctx, rk_socket_t fd, krb5_data *data)
{
    struct request *request = ctx;
    krb5_data ap_req_data, krb_priv_data, passwd_data;
    krb5_storage *sp = NULL;
    krb5_error_code ret;
    krb5_ssize_t slen;
    size_t len;

    krb5_data_zero(&ap_req_data);
    krb5_data_zero(&krb_priv_data);

    ret = krb5_auth_con_genaddrs(context, request->ac, fd,
                                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR);
    if (ret)
        goto out;

    ret = krb5_mk_req_extended(context,
                               &request->ac,
                               AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
                               NULL,
                               request->creds,
                               &ap_req_data);
    if (ret)
        goto out;

    passwd_data.data   = rk_UNCONST(request->password);
    passwd_data.length = strlen(request->password);

    ret = krb5_mk_priv(context,
                       request->ac,
                       &passwd_data,
                       &krb_priv_data,
                       NULL);
    if (ret)
        goto out;

    sp = krb5_storage_emem();
    if (sp == NULL) {
        ret = ENOMEM;
        goto out;
    }

    len = 6 + ap_req_data.length + krb_priv_data.length;

    ret = krb5_store_uint16(sp, len);
    if (ret) goto out;
    ret = krb5_store_uint16(sp, 1);
    if (ret) goto out;
    ret = krb5_store_uint16(sp, ap_req_data.length);
    if (ret) goto out;
    slen = krb5_storage_write(sp, ap_req_data.data, ap_req_data.length);
    if (slen != ap_req_data.length) {
        ret = EINVAL;
        goto out;
    }
    slen = krb5_storage_write(sp, krb_priv_data.data, krb_priv_data.length);
    if (slen != krb_priv_data.length) {
        ret = EINVAL;
        goto out;
    }

    ret = krb5_storage_to_data(sp, data);

out:
    if (ret)
        _krb5_debugx(context, 10, "chgpw_prexmit failed with: %d", ret);
    if (sp)
        krb5_storage_free(sp);
    krb5_data_free(&krb_priv_data);
    krb5_data_free(&ap_req_data);
    return ret;
}
Exemplo n.º 9
0
static krb5_error_code
setpw_prexmit(krb5_context context, int proto,
              void *ctx, int fd, krb5_data *data)
{
    struct request *request = ctx;
    krb5_data ap_req_data, krb_priv_data, pwd_data;
    krb5_error_code ret;
    ChangePasswdDataMS chpw;
    krb5_storage *sp = NULL;
    ssize_t slen;
    size_t len;

    krb5_data_zero(&ap_req_data);
    krb5_data_zero(&krb_priv_data);
    krb5_data_zero(&pwd_data);

    ret = krb5_auth_con_genaddrs(context, request->ac, fd,
                                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR);
    if (ret)
        goto out;

    ret = krb5_mk_req_extended(context,
                               &request->ac,
                               AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
                               NULL,
                               request->creds,
                               &ap_req_data);
    if (ret)
        goto out;

    chpw.newpasswd.length = strlen(request->password);
    chpw.newpasswd.data = rk_UNCONST(request->password);
    if (request->target) {
        chpw.targname = &request->target->name;
        chpw.targrealm = &request->target->realm;
    } else {
        chpw.targname = NULL;
        chpw.targrealm = NULL;
    }

    ASN1_MALLOC_ENCODE(ChangePasswdDataMS, pwd_data.data, pwd_data.length,
                       &chpw, &len, ret);
    if (ret)
        goto out;
    if(pwd_data.length != len)
        krb5_abortx(context, "internal error in ASN.1 encoder");

    ret = krb5_mk_priv (context,
                        request->ac,
                        &pwd_data,
                        &krb_priv_data,
                        NULL);
    if (ret)
        goto out;

    sp = krb5_storage_emem();
    if (sp == NULL) {
        ret = ENOMEM;
        goto out;
    }

    len = 6 + ap_req_data.length + krb_priv_data.length;

    ret = krb5_store_uint16(sp, len);
    if (ret) goto out;
    ret = krb5_store_uint16(sp, 0xff80);
    if (ret) goto out;
    ret = krb5_store_uint16(sp, ap_req_data.length);
    if (ret) goto out;
    slen = krb5_storage_write(sp, ap_req_data.data, ap_req_data.length);
    if (slen != ap_req_data.length) {
        ret = EINVAL;
        goto out;
    }
    slen = krb5_storage_write(sp, krb_priv_data.data, krb_priv_data.length);
    if (slen != krb_priv_data.length) {
        ret = EINVAL;
        goto out;
    }

    ret = krb5_storage_to_data(sp, data);

out:
    if (ret)
        _krb5_debugx(context, 10, "setpw_prexmit failed with %d", ret);
    if (sp)
        krb5_storage_free(sp);
    krb5_data_free(&krb_priv_data);
    krb5_data_free(&ap_req_data);
    krb5_data_free(&pwd_data);

    return ret;
}
/*
 * Try krb5 authentication. server_user is passed for logging purposes
 * only, in auth is received ticket, in client is returned principal
 * from the ticket
 */
int
auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client)
{
	krb5_error_code problem;
	krb5_principal server;
	krb5_data reply;
	krb5_ticket *ticket;
	int fd, ret;

	ret = 0;
	server = NULL;
	ticket = NULL;
	reply.length = 0;

	problem = krb5_init(authctxt);
	if (problem)
		goto err;

	problem = krb5_auth_con_init(authctxt->krb5_ctx,
	    &authctxt->krb5_auth_ctx);
	if (problem)
		goto err;

	fd = packet_get_connection_in();
#ifdef HEIMDAL
	problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx,
	    authctxt->krb5_auth_ctx, &fd);
#else
	problem = krb5_auth_con_genaddrs(authctxt->krb5_ctx, 
	    authctxt->krb5_auth_ctx,fd,
	    KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR |
	    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
#endif
	if (problem)
		goto err;

	problem = krb5_sname_to_principal(authctxt->krb5_ctx,  NULL, NULL ,
	    KRB5_NT_SRV_HST, &server);
	if (problem)
		goto err;

	problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx,
	    auth, server, NULL, NULL, &ticket);
	if (problem)
		goto err;

#ifdef HEIMDAL
	problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client,
	    &authctxt->krb5_user);
#else
	problem = krb5_copy_principal(authctxt->krb5_ctx, 
				      ticket->enc_part2->client,
				      &authctxt->krb5_user);
#endif
	if (problem)
		goto err;

	/* if client wants mutual auth */
	problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
	    &reply);
	if (problem)
		goto err;

	/* Check .k5login authorization now. */
	if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
	    authctxt->pw->pw_name))
		goto err;

	if (client)
		krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
		    client);

	packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
	packet_put_string((char *) reply.data, reply.length);
	packet_send();
	packet_write_wait();

	ret = 1;
 err:
	if (server)
		krb5_free_principal(authctxt->krb5_ctx, server);
	if (ticket)
		krb5_free_ticket(authctxt->krb5_ctx, ticket);
	if (reply.length)
		xfree(reply.data);

	if (problem) {
		if (authctxt->krb5_ctx != NULL)
			debug("Kerberos v5 authentication failed: %s",
			    krb5_get_err_text(authctxt->krb5_ctx, problem));
		else
			debug("Kerberos v5 authentication failed: %d",
			    problem);
	}

	return (ret);
}
Exemplo n.º 11
0
void
kerberos5_forward (TN_Authenticator * ap)
{
  krb5_error_code r;
  krb5_ccache ccache;
  krb5_principal client = 0;
  krb5_principal server = 0;
  krb5_data forw_creds;

  forw_creds.data = 0;

  if ((r = krb5_cc_default (telnet_context, &ccache)))
    {
      DEBUG (("Kerberos V5: could not get default ccache - %s\r\n",
	      error_message (r)));
      return;
    }

  for (;;)			/* Fake loop */
    {
      if ((r = krb5_cc_get_principal (telnet_context, ccache, &client)))
	{
	  DEBUG (("Kerberos V5: could not get default principal - %s\r\n",
		  error_message (r)));
	  break;
	}
      if ((r =
	   krb5_sname_to_principal (telnet_context, RemoteHostName, "host",
				    KRB5_NT_SRV_HST, &server)))
	{
	  DEBUG (("Kerberos V5: could not make server principal - %s\r\n",
		  error_message (r)));
	  break;
	}
      if ((r = krb5_auth_con_genaddrs (telnet_context, auth_context, net,
				       KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)))
	{
	  DEBUG (("Kerberos V5: could not gen local full address - %s\r\n",
		  error_message (r)));
	  break;
	}
      if ((r = krb5_fwd_tgt_creds (telnet_context, auth_context, 0, client,
				   server, ccache,
				   forward_flags & OPTS_FORWARDABLE_CREDS,
				   &forw_creds)))
	{
	  DEBUG (("Kerberos V5: error getting forwarded creds - %s\r\n",
		  error_message (r)));
	  break;
	}

      /* Send forwarded credentials */
      if (!Data (ap, KRB_FORWARD, forw_creds.data, forw_creds.length))
	{
	  DEBUG (("Not enough room for authentication data\r\n"));
	}
      else
	{
	  DEBUG (("Forwarded local Kerberos V5 credentials to server\r\n"));
	}
      break;
    }

  if (client)
    krb5_free_principal (telnet_context, client);
  if (server)
    krb5_free_principal (telnet_context, server);
  free (forw_creds.data);
  krb5_cc_close (telnet_context, ccache);
}