Esempio n. 1
0
static int
proto (int sock, const char *hostname, const char *svc,
       char *message, size_t len)
{
    krb5_auth_context auth_context;
    krb5_error_code status;
    krb5_principal server;
    krb5_data data;
    krb5_data data_send;

    krb5_ccache     ccache;
    krb5_creds      creds;
    krb5_kdc_flags  flags;
    krb5_principal  principal;

    status = krb5_auth_con_init (context, &auth_context);
    if (status) {
	krb5_warn (context, status, "krb5_auth_con_init");
	return 1;
    }

    status = krb5_auth_con_setaddrs_from_fd (context,
					     auth_context,
					     &sock);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_auth_con_setaddr");
	return 1;
    }

    status = krb5_sname_to_principal (context,
				      hostname,
				      svc,
				      KRB5_NT_SRV_HST,
				      &server);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_sname_to_principal");
	return 1;
    }

    status = krb5_sendauth (context,
			    &auth_context,
			    &sock,
			    KF_VERSION_1,
			    NULL,
			    server,
			    AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
			    NULL,
			    NULL,
			    NULL,
			    NULL,
			    NULL,
			    NULL);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn(context, status, "krb5_sendauth");
	return 1;
    }

    if (ccache_name == NULL)
	ccache_name = "";

    data_send.data   = (void *)remote_name;
    data_send.length = strlen(remote_name) + 1;
    status = krb5_write_priv_message(context, auth_context, &sock, &data_send);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_write_message");
	return 1;
    }
    data_send.data   = (void *)ccache_name;
    data_send.length = strlen(ccache_name)+1;
    status = krb5_write_priv_message(context, auth_context, &sock, &data_send);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_write_message");
	return 1;
    }

    memset (&creds, 0, sizeof(creds));

    status = krb5_cc_default (context, &ccache);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_cc_default");
	return 1;
    }

    status = krb5_cc_get_principal (context, ccache, &principal);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_cc_get_principal");
	return 1;
    }

    creds.client = principal;

    status = krb5_make_principal (context,
				  &creds.server,
				  principal->realm,
				  KRB5_TGS_NAME,
				  principal->realm,
				  NULL);

    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_make_principal");
	return 1;
    }

    creds.times.endtime = 0;

    flags.i = 0;
    flags.b.forwarded   = 1;
    flags.b.forwardable = forwardable;

    status = krb5_get_forwarded_creds (context,
				       auth_context,
				       ccache,
				       flags.i,
				       hostname,
				       &creds,
				       &data);
    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_get_forwarded_creds");
	return 1;
    }

    status = krb5_write_priv_message(context, auth_context, &sock, &data);

    if (status) {
	krb5_auth_con_free(context, auth_context);
	krb5_warn (context, status, "krb5_mk_priv");
	return 1;
    }

    krb5_data_free (&data);

    status = krb5_read_priv_message(context, auth_context, &sock, &data);
    krb5_auth_con_free(context, auth_context);
    if (status) {
	krb5_warn (context, status, "krb5_mk_priv");
	return 1;
    }
    if(data.length >= len) {
	krb5_warnx (context, "returned string is too long, truncating");
	memcpy(message, data.data, len);
	message[len - 1] = '\0';
    } else {
	memcpy(message, data.data, data.length);
	message[data.length] = '\0';
    }
    krb5_data_free (&data);

    return(strcmp(message, "ok"));
}
Esempio n. 2
0
static int
proto (int sock, const char *hostname, const char *service)
{
    krb5_auth_context auth_context;
    krb5_error_code status;
    krb5_principal server;
    krb5_data data;
    krb5_data packet;
    u_int32_t len, net_len;

    status = krb5_auth_con_init (context, &auth_context);
    if (status)
	krb5_err (context, 1, status, "krb5_auth_con_init");

    status = krb5_auth_con_setaddrs_from_fd (context,
					     auth_context,
					     &sock);
    if (status)
	krb5_err (context, 1, status, "krb5_auth_con_setaddrs_from_fd");

    status = krb5_sname_to_principal (context,
				      hostname,
				      service,
				      KRB5_NT_SRV_HST,
				      &server);
    if (status)
	krb5_err (context, 1, status, "krb5_sname_to_principal");

    status = krb5_sendauth (context,
			    &auth_context,
			    &sock,
			    VERSION,
			    NULL,
			    server,
			    AP_OPTS_MUTUAL_REQUIRED,
			    NULL,
			    NULL,
			    NULL,
			    NULL,
			    NULL,
			    NULL);
    if (status)
	krb5_err (context, 1, status, "krb5_sendauth");

    data.data   = "hej";
    data.length = 3;

    krb5_data_zero (&packet);

    status = krb5_mk_safe (context,
			   auth_context,
			   &data,
			   &packet,
			   NULL);
    if (status)
	krb5_err (context, 1, status, "krb5_mk_safe");

    len = packet.length;
    net_len = htonl(len);

    if (krb5_net_write (context, &sock, &net_len, 4) != 4)
	err (1, "krb5_net_write");
    if (krb5_net_write (context, &sock, packet.data, len) != len)
	err (1, "krb5_net_write");

    data.data   = "hemligt";
    data.length = 7;

    krb5_data_free (&packet);

    status = krb5_mk_priv (context,
			   auth_context,
			   &data,
			   &packet,
			   NULL);
    if (status)
	krb5_err (context, 1, status, "krb5_mk_priv");

    len = packet.length;
    net_len = htonl(len);

    if (krb5_net_write (context, &sock, &net_len, 4) != 4)
	err (1, "krb5_net_write");
    if (krb5_net_write (context, &sock, packet.data, len) != len)
	err (1, "krb5_net_write");
    return 0;
}
Esempio n. 3
0
void
kerberos5_is(Authenticator *ap, unsigned char *data, int cnt)
{
    krb5_error_code ret;
    krb5_data outbuf;
    krb5_keyblock *key_block;
    char *name;
    krb5_principal server;
    krb5_authenticator authenticator;
    int zero = 0;

    if (cnt-- < 1)
	return;
    switch (*data++) {
    case KRB_AUTH:
	auth.data = (char *)data;
	auth.length = cnt;

	auth_context = NULL;

	ret = krb5_auth_con_init (context, &auth_context);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	ret = krb5_auth_con_setaddrs_from_fd (context,
					      auth_context,
					      &zero);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	ret = krb5_sock_to_principal (context,
				      0,
				      "host",
				      KRB5_NT_SRV_HST,
				      &server);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_sock_to_principal failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	ret = krb5_rd_req(context,
			  &auth_context,
			  &auth, 
			  server,
			  NULL,
			  NULL,
			  &ticket);
	krb5_free_principal (context, server);

	if (ret) {
	    char *errbuf;

	    asprintf(&errbuf,
		     "Read req failed: %s",
		     krb5_get_err_text(context, ret));
	    Data(ap, KRB_REJECT, errbuf, -1);
	    if (auth_debug_mode)
		printf("%s\r\n", errbuf);
	    free (errbuf);
	    return;
	}

	ret = krb5_auth_con_getkey(context, auth_context, &key_block);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_getkey failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}
	
	ret = krb5_auth_getauthenticator (context,
					  auth_context,
					  &authenticator);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_getauthenticator failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_getauthenticator failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	if (authenticator->cksum) {
	    char foo[2];

	    foo[0] = ap->type;
	    foo[1] = ap->way;

	    ret = krb5_verify_checksum (context,
					foo,
					sizeof(foo),
					key_block,
					authenticator->cksum);
	    if (ret) {
		Data(ap, KRB_REJECT, "No checksum", -1);
		if (auth_debug_mode)
		    printf ("No checksum\r\n");
		krb5_free_authenticator (context,
					 &authenticator);
		
		return;
	    }
	}
	krb5_free_authenticator (context,
				 &authenticator);

	ret = krb5_auth_con_getremotesubkey (context,
					     auth_context,
					     &key_block);

	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_getremotesubkey failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
	    ret = krb5_mk_rep(context, &auth_context, &outbuf);
	    if (ret) {
		Data(ap, KRB_REJECT,
		     "krb5_mk_rep failed", -1);
		auth_finished(ap, AUTH_REJECT);
		if (auth_debug_mode)
		    printf("Kerberos V5: "
			   "krb5_mk_rep failed (%s)\r\n",
			   krb5_get_err_text(context, ret));
		return;
	    }
	    Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
	}
	if (krb5_unparse_name(context, ticket->client, &name))
	    name = 0;

	if(UserNameRequested && krb5_kuserok(context,
					     ticket->client,
					     UserNameRequested)) {
	    Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
	    if (auth_debug_mode) {
		printf("Kerberos5 identifies him as ``%s''\r\n",
		       name ? name : "");
	    }

	    if(key_block->keytype == KEYTYPE_DES) {
		Session_Key skey;

		skey.type = SK_DES;
		skey.length = 8;
		skey.data = key_block->keyvalue.data;
		encrypt_session_key(&skey, 0);
	    }

	} else {
	    char *msg;

	    asprintf (&msg, "user `%s' is not authorized to "
		      "login as `%s'", 
		      name ? name : "<unknown>",
		      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);

	krb5_free_keyblock_contents(context, key_block);
	
	break;
#ifdef	FORWARD
    case KRB_FORWARD: {
	struct passwd *pwd;
	char ccname[1024];	/* XXX */
	krb5_data inbuf;
	krb5_ccache ccache;
	inbuf.data = (char *)data;
	inbuf.length = cnt;

	pwd = getpwnam (UserNameRequested);
	if (pwd == NULL)
	    break;

	snprintf (ccname, sizeof(ccname),
		  "FILE:/tmp/krb5cc_%u", pwd->pw_uid);

	ret = krb5_cc_resolve (context, ccname, &ccache);
	if (ret) {
	    if (auth_debug_mode)
		printf ("Kerberos V5: could not get ccache: %s\r\n",
			krb5_get_err_text(context, ret));
	    break;
	}

	ret = krb5_cc_initialize (context,
				  ccache,
				  ticket->client);
	if (ret) {
	    if (auth_debug_mode)
		printf ("Kerberos V5: could not init ccache: %s\r\n",
			krb5_get_err_text(context, ret));
	    break;
	}

	ret = krb5_rd_cred (context,
			    auth_context,
			    ccache,
			    &inbuf);
	if(ret) {
	    char *errbuf;

	    asprintf (&errbuf,
		      "Read forwarded creds failed: %s",
		      krb5_get_err_text (context, ret));
	    if(errbuf == NULL)
		Data(ap, KRB_FORWARD_REJECT, NULL, 0);
	    else
		Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
	    if (auth_debug_mode)
		printf("Could not read forwarded credentials: %s\r\n",
		       errbuf);
	    free (errbuf);
	} else
	    Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
	chown (ccname + 5, pwd->pw_uid, -1);
	if (auth_debug_mode)
	    printf("Forwarded credentials obtained\r\n");
	break;
    }
#endif	/* FORWARD */
    default:
	if (auth_debug_mode)
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
	Data(ap, KRB_REJECT, 0, 0);
	break;
    }
}
Esempio n. 4
0
static int
proto (int sock, const char *service)
{
    krb5_auth_context auth_context;
    krb5_error_code status;
    krb5_principal server;
    krb5_ticket *ticket;
    char *name;
    char hostname[MAXHOSTNAMELEN];
    krb5_data packet;
    krb5_data data;
    u_int32_t len, net_len;
    ssize_t n;

    status = krb5_auth_con_init (context, &auth_context);
    if (status)
	krb5_err (context, 1, status, "krb5_auth_con_init");

    status = krb5_auth_con_setaddrs_from_fd (context,
					     auth_context,
					     &sock);

    if (status)
	krb5_err (context, 1, status, "krb5_auth_con_setaddrs_from_fd");

    if(gethostname (hostname, sizeof(hostname)) < 0)
	krb5_err (context, 1, errno, "gethostname");

    status = krb5_sname_to_principal (context,
				      hostname,
				      service,
				      KRB5_NT_SRV_HST,
				      &server);
    if (status)
	krb5_err (context, 1, status, "krb5_sname_to_principal");

    status = krb5_recvauth (context,
			    &auth_context,
			    &sock,
			    VERSION,
			    server,
			    0,
			    NULL,
			    &ticket);
    if (status)
	krb5_err (context, 1, status, "krb5_recvauth");

    status = krb5_unparse_name (context,
				ticket->client,
				&name);
    if (status)
	krb5_err (context, 1, status, "krb5_unparse_name");

    fprintf (stderr, "User is `%s'\n", name);
    free (name);

    krb5_data_zero (&data);
    krb5_data_zero (&packet);

    n = krb5_net_read (context, &sock, &net_len, 4);
    if (n == 0)
	krb5_errx (context, 1, "EOF in krb5_net_read");
    if (n < 0)
	krb5_err (context, 1, errno, "krb5_net_read");

    len = ntohl(net_len);

    krb5_data_alloc (&packet, len);

    n = krb5_net_read (context, &sock, packet.data, len);
    if (n == 0)
	krb5_errx (context, 1, "EOF in krb5_net_read");
    if (n < 0)
	krb5_err (context, 1, errno, "krb5_net_read");
    
    status = krb5_rd_safe (context,
			   auth_context,
			   &packet,
			   &data,
			   NULL);
    if (status)
	krb5_err (context, 1, status, "krb5_rd_safe");

    fprintf (stderr, "safe packet: %.*s\n", (int)data.length,
	    (char *)data.data);

    n = krb5_net_read (context, &sock, &net_len, 4);
    if (n == 0)
	krb5_errx (context, 1, "EOF in krb5_net_read");
    if (n < 0)
	krb5_err (context, 1, errno, "krb5_net_read");

    len = ntohl(net_len);

    krb5_data_alloc (&packet, len);

    n = krb5_net_read (context, &sock, packet.data, len);
    if (n == 0)
	krb5_errx (context, 1, "EOF in krb5_net_read");
    if (n < 0)
	krb5_err (context, 1, errno, "krb5_net_read");
    
    status = krb5_rd_priv (context,
			   auth_context,
			   &packet,
			   &data,
			   NULL);
    if (status)
	krb5_err (context, 1, status, "krb5_rd_priv");

    fprintf (stderr, "priv packet: %.*s\n", (int)data.length,
	    (char *)data.data);

    return 0;
}
Esempio n. 5
0
/**
 * Perform the server side of the sendauth protocol like krb5_recvauth(), but support
 * a user-specified callback, \a match_appl_version, to perform the match of the application
 * version \a match_data.
 */
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_recvauth_match_version(krb5_context context,
			    krb5_auth_context *auth_context,
			    krb5_pointer p_fd,
			    krb5_boolean (*match_appl_version)(const void *,
							       const char*),
			    const void *match_data,
			    krb5_principal server,
			    int32_t flags,
			    krb5_keytab keytab,
			    krb5_ticket **ticket)
{
    krb5_error_code ret;
    const char *version = KRB5_SENDAUTH_VERSION;
    char her_version[sizeof(KRB5_SENDAUTH_VERSION)];
    char *her_appl_version;
    uint32_t len;
    u_char repl;
    krb5_data data;
    krb5_flags ap_options;
    ssize_t n;

    /*
     * If there are no addresses in auth_context, get them from `fd'.
     */

    if (*auth_context == NULL) {
	ret = krb5_auth_con_init (context, auth_context);
	if (ret)
	    return ret;
    }

    ret = krb5_auth_con_setaddrs_from_fd (context,
					  *auth_context,
					  p_fd);
    if (ret)
	return ret;

    /*
     * Expect SENDAUTH protocol version.
     */
    if(!(flags & KRB5_RECVAUTH_IGNORE_VERSION)) {
	n = krb5_net_read (context, p_fd, &len, 4);
	if (n < 0) {
	    ret = errno;
	    krb5_set_error_message(context, ret, "read: %s", strerror(ret));
	    return ret;
	}
	if (n == 0) {
	    krb5_set_error_message(context, KRB5_SENDAUTH_BADAUTHVERS,
				   N_("Failed to receive sendauth data", ""));
	    return KRB5_SENDAUTH_BADAUTHVERS;
	}
	len = ntohl(len);
	if (len != sizeof(her_version)
	    || krb5_net_read (context, p_fd, her_version, len) != len
	    || strncmp (version, her_version, len)) {
	    repl = 1;
	    krb5_net_write (context, p_fd, &repl, 1);
	    krb5_clear_error_message (context);
	    return KRB5_SENDAUTH_BADAUTHVERS;
	}
    }

    /*
     * Expect application protocol version.
     */
    n = krb5_net_read (context, p_fd, &len, 4);
    if (n < 0) {
	ret = errno;
	krb5_set_error_message(context, ret, "read: %s", strerror(ret));
	return ret;
    }
    if (n == 0) {
	krb5_clear_error_message (context);
	return KRB5_SENDAUTH_BADAPPLVERS;
    }
    len = ntohl(len);
    her_appl_version = malloc (len);
    if (her_appl_version == NULL) {
	repl = 2;
	krb5_net_write (context, p_fd, &repl, 1);
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }
    if (krb5_net_read (context, p_fd, her_appl_version, len) != len
	|| !(*match_appl_version)(match_data, her_appl_version)) {
	repl = 2;
	krb5_net_write (context, p_fd, &repl, 1);
	krb5_set_error_message(context, KRB5_SENDAUTH_BADAPPLVERS,
			       N_("wrong sendauth application version (%s)", ""),
			       her_appl_version);
	free (her_appl_version);
	return KRB5_SENDAUTH_BADAPPLVERS;
    }
    free (her_appl_version);

    /*
     * Send OK.
     */
    repl = 0;
    if (krb5_net_write (context, p_fd, &repl, 1) != 1) {
	ret = errno;
	krb5_set_error_message(context, ret, "write: %s", strerror(ret));
	return ret;
    }

    /*
     * Until here, the fields in the message were in cleartext and unauthenticated.
     * From now on, Kerberos kicks in.
     */

    /*
     * Expect AP_REQ.
     */
    krb5_data_zero (&data);
    ret = krb5_read_message (context, p_fd, &data);
    if (ret)
	return ret;

    ret = krb5_rd_req (context,
		       auth_context,
		       &data,
		       server,
		       keytab,
		       &ap_options,
		       ticket);
    krb5_data_free (&data);
    if (ret) {
	krb5_data error_data;
	krb5_error_code ret2;

	ret2 = krb5_mk_error (context,
			      ret,
			      NULL,
			      NULL,
			      NULL,
			      server,
			      NULL,
			      NULL,
			      &error_data);
	if (ret2 == 0) {
	    krb5_write_message (context, p_fd, &error_data);
	    krb5_data_free (&error_data);
	}
	return ret;
    }

    /*
     * Send OK.
     */
    len = 0;
    if (krb5_net_write (context, p_fd, &len, 4) != 4) {
	ret = errno;
	krb5_set_error_message(context, ret, "write: %s", strerror(ret));
	krb5_free_ticket(context, *ticket);
	*ticket = NULL;
	return ret;
    }

    /*
     * If client requires mutual authentication, send AP_REP.
     */
    if (ap_options & AP_OPTS_MUTUAL_REQUIRED) {
	ret = krb5_mk_rep (context, *auth_context, &data);
	if (ret) {
	    krb5_free_ticket(context, *ticket);
	    *ticket = NULL;
	    return ret;
	}

	ret = krb5_write_message (context, p_fd, &data);
	if (ret) {
	    krb5_free_ticket(context, *ticket);
	    *ticket = NULL;
	    return ret;
	}
	krb5_data_free (&data);
    }
    return 0;
}
Esempio n. 6
0
static int
kerberos5_send(char *name, Authenticator *ap)
{
    krb5_error_code ret;
    krb5_ccache ccache;
    int ap_opts;
    krb5_data cksum_data;
    char foo[2];

    if(check_krb5_tickets() != 1)
	return 0;
    
    if (!UserNameRequested) {
	if (auth_debug_mode) {
	    printf("Kerberos V5: no user name supplied\r\n");
	}
	return(0);
    }
    
    ret = krb5_cc_default(context, &ccache);
    if (ret) {
	if (auth_debug_mode) {
	    printf("Kerberos V5: could not get default ccache: %s\r\n",
		   krb5_get_err_text (context, ret));
	}
	return 0;
    }
	
    if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
	ap_opts = AP_OPTS_MUTUAL_REQUIRED;
    else
	ap_opts = 0;
    
    ap_opts |= AP_OPTS_USE_SUBKEY;
    
    ret = krb5_auth_con_init (context, &auth_context);
    if (ret) {
	if (auth_debug_mode) {
	    printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
		   krb5_get_err_text(context, ret));
	}
	return(0);
    }

    ret = krb5_auth_con_setaddrs_from_fd (context,
					  auth_context,
					  &net);
    if (ret) {
	if (auth_debug_mode) {
	    printf ("Kerberos V5:"
		    " krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
		    krb5_get_err_text(context, ret));
	}
	return(0);
    }

    krb5_auth_con_setkeytype (context, auth_context, KEYTYPE_DES);

    foo[0] = ap->type;
    foo[1] = ap->way;

    cksum_data.length = sizeof(foo);
    cksum_data.data   = foo;


    {
	krb5_principal service;
	char sname[128];


	ret = krb5_sname_to_principal (context,
				       RemoteHostName,
				       NULL,
				       KRB5_NT_SRV_HST,
				       &service);
	if(ret) {
	    if (auth_debug_mode) {
		printf ("Kerberos V5:"
			" krb5_sname_to_principal(%s) failed (%s)\r\n",
			RemoteHostName, krb5_get_err_text(context, ret));
	    }
	    return 0;
	}
	ret = krb5_unparse_name_fixed(context, service, sname, sizeof(sname));
	if(ret) {
	    if (auth_debug_mode) {
		printf ("Kerberos V5:"
			" krb5_unparse_name_fixed failed (%s)\r\n",
			krb5_get_err_text(context, ret));
	    }
	    return 0;
	}
	printf("[ Trying %s (%s)... ]\r\n", name, sname);
	ret = krb5_mk_req_exact(context, &auth_context, ap_opts,
				service, 
				&cksum_data, ccache, &auth);
	krb5_free_principal (context, service);

    }
    if (ret) {
	if (1 || auth_debug_mode) {
	    printf("Kerberos V5: mk_req failed (%s)\r\n",
		   krb5_get_err_text(context, ret));
	}
	return(0);
    }

    if (!auth_sendname((unsigned char *)UserNameRequested,
		       strlen(UserNameRequested))) {
	if (auth_debug_mode)
	    printf("Not enough room for user name\r\n");
	return(0);
    }
    if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
	if (auth_debug_mode)
	    printf("Not enough room for authentication data\r\n");
	return(0);
    }
    if (auth_debug_mode) {
	printf("Sent Kerberos V5 credentials to server\r\n");
    }
    return(1);
}
Esempio n. 7
0
static int
proto (int sock, const char *svc)
{
    krb5_auth_context auth_context;
    krb5_error_code status;
    krb5_principal server;
    krb5_ticket *ticket;
    char *name;
    char ret_string[10];
    char hostname[MAXHOSTNAMELEN];
    krb5_data data;
    krb5_data remotename;
    krb5_data tk_file;
    krb5_ccache ccache;
    char ccname[MAXPATHLEN];
    struct passwd *pwd;

    status = krb5_auth_con_init (context, &auth_context);
    if (status)
	krb5_err(context, 1, status, "krb5_auth_con_init");

    status = krb5_auth_con_setaddrs_from_fd (context,
					     auth_context,
					     &sock);
    if (status)
	krb5_err(context, 1, status, "krb5_auth_con_setaddr");

    if(gethostname (hostname, sizeof(hostname)) < 0)
	krb5_err(context, 1, errno, "gethostname");

    status = krb5_sname_to_principal (context,
				      hostname,
				      svc,
				      KRB5_NT_SRV_HST,
				      &server);
    if (status)
	krb5_err(context, 1, status, "krb5_sname_to_principal");

    status = krb5_recvauth_match_version (context,
					  &auth_context,
					  &sock,
					  kfd_match_version,
					  NULL,
					  server,
					  0,
					  NULL,
					  &ticket);
    if (status)
	krb5_err(context, 1, status, "krb5_recvauth");

    status = krb5_unparse_name (context,
				ticket->client,
				&name);
    if (status)
	krb5_err(context, 1, status, "krb5_unparse_name");

    if(protocol_version == 0) {
	data.data = "old clnt"; /* XXX old clients only had room for
                                   10 bytes of message, and also
                                   didn't show it to the user */
	data.length = strlen(data.data) + 1;
	krb5_write_message(context, &sock, &data);
	sleep(2); /* XXX give client time to finish */
	krb5_errx(context, 1, "old client; exiting");
    }

    status=krb5_read_priv_message (context, auth_context,
				   &sock, &remotename);
    if (status)
	krb5_err(context, 1, status, "krb5_read_message");
    status=krb5_read_priv_message (context, auth_context,
				   &sock, &tk_file);
    if (status)
	krb5_err(context, 1, status, "krb5_read_message");

    krb5_data_zero (&data);

    if(((char*)remotename.data)[remotename.length-1] != '\0')
	krb5_errx(context, 1, "unterminated received");
    if(((char*)tk_file.data)[tk_file.length-1] != '\0')
	krb5_errx(context, 1, "unterminated received");

    status = krb5_read_priv_message(context, auth_context, &sock, &data);

    if (status) {
	krb5_err(context, 1, errno, "krb5_read_priv_message");
	goto out;
    }

    pwd = getpwnam ((char *)(remotename.data));
    if (pwd == NULL) {
	status=1;
	krb5_warnx(context, "getpwnam: %s failed",(char *)(remotename.data));
	goto out;
    }

    if(!krb5_kuserok (context,
		      ticket->client,
		      (char *)(remotename.data))) {
	status=1;
	krb5_warnx(context, "krb5_kuserok: permission denied");
	goto out;
    }

    if (setgid(pwd->pw_gid) < 0) {
	krb5_warn(context, errno, "setgid");
	goto out;
    }
    if (setuid(pwd->pw_uid) < 0) {
	krb5_warn(context, errno, "setuid");
	goto out;
    }

    if (tk_file.length != 1)
	snprintf (ccname, sizeof(ccname), "%s", (char *)(tk_file.data));
    else
	snprintf (ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%lu",
		  (unsigned long)pwd->pw_uid);

    status = krb5_cc_resolve (context, ccname, &ccache);
    if (status) {
	krb5_warn(context, status, "krb5_cc_resolve");
        goto out;
    }
    status = krb5_cc_initialize (context, ccache, ticket->client);
    if (status) {
	krb5_warn(context, status, "krb5_cc_initialize");
        goto out;
    }
    status = krb5_rd_cred2 (context, auth_context, ccache, &data);
    krb5_cc_close (context, ccache);
    if (status) {
	krb5_warn(context, status, "krb5_rd_cred");
        goto out;

    }
    strlcpy(krb5_tkfile,ccname,sizeof(krb5_tkfile));
    krb5_warnx(context, "%s forwarded ticket to %s,%s",
	       name,
	       (char *)(remotename.data),ccname);
  out:
    if (status) {
	strlcpy(ret_string, "no", sizeof(ret_string));
	krb5_warnx(context, "failed");
    } else  {
	strlcpy(ret_string, "ok", sizeof(ret_string));
    }

    krb5_data_free (&tk_file);
    krb5_data_free (&remotename);
    krb5_data_free (&data);
    free(name);

    data.data = ret_string;
    data.length = strlen(ret_string) + 1;
    status = krb5_write_priv_message(context, auth_context, &sock, &data);
    krb5_auth_con_free(context, auth_context);

    return status;
}
Esempio n. 8
0
/*
 * 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_data *reply)
{
	krb5_error_code problem;
	krb5_principal server;
	krb5_ticket *ticket;
	int fd, ret;
	const char *errtxt;

	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();
	problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx,
	    authctxt->krb5_auth_ctx, &fd);
	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;

	problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client,
	    &authctxt->krb5_user);
	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);

	ret = 1;
 err:
	if (server)
		krb5_free_principal(authctxt->krb5_ctx, server);
	if (ticket)
		krb5_free_ticket(authctxt->krb5_ctx, ticket);
	if (!ret && reply->length) {
		free(reply->data);
		memset(reply, 0, sizeof(*reply));
	}

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

	return (ret);
}
Esempio n. 9
0
static int
send_krb5_auth(int s,
	       struct sockaddr *thisaddr,
	       struct sockaddr *thataddr,
	       const char *hostname,
	       const char *remote_user,
	       const char *local_user,
	       size_t cmd_len,
	       const char *cmd)
{
    krb5_principal server;
    krb5_data cksum_data;
    int status;
    size_t len;
    krb5_auth_context auth_context = NULL;
    const char *protocol_string = NULL;
    krb5_flags ap_opts;
    char *str;

    status = krb5_sname_to_principal(context,
				     hostname,
				     "host",
				     KRB5_NT_SRV_HST,
				     &server);
    if (status) {
	warnx ("%s: %s", hostname, krb5_get_err_text(context, status));
	return 1;
    }

    if(do_encrypt == -1) {
	krb5_appdefault_boolean(context, NULL,
				krb5_principal_get_realm(context, server),
				"encrypt",
				FALSE,
				&do_encrypt);
    }

    cksum_data.length = asprintf (&str,
				  "%u:%s%s%s",
				  ntohs(socket_get_port(thataddr)),
				  do_encrypt ? "-x " : "",
				  cmd,
				  remote_user);
    if (str == NULL) {
	warnx ("%s: failed to allocate command", hostname);
	return 1;
    }
    cksum_data.data = str;

    ap_opts = 0;

    if(do_encrypt)
	ap_opts |= AP_OPTS_MUTUAL_REQUIRED;

    switch(protocol_version) {
    case 2:
	ap_opts |= AP_OPTS_USE_SUBKEY;
	protocol_string = KCMD_NEW_VERSION;
	break;
    case 1:
	protocol_string = KCMD_OLD_VERSION;
	key_usage = KRB5_KU_OTHER_ENCRYPTED;
	break;
    default:
	abort();
    }
	
    status = krb5_sendauth (context,
			    &auth_context,
			    &s,
			    protocol_string,
			    NULL,
			    server,
			    ap_opts,
			    &cksum_data,
			    NULL,
			    NULL,
			    NULL,
			    NULL,
			    NULL);

    /* do this while we have a principal */
    if(do_forward == -1 || do_forwardable == -1) {
	krb5_const_realm realm = krb5_principal_get_realm(context, server);
	if (do_forwardable == -1)
	    krb5_appdefault_boolean(context, NULL, realm,
				    "forwardable", FALSE,
				    &do_forwardable);
	if (do_forward == -1)
	    krb5_appdefault_boolean(context, NULL, realm,
				    "forward", FALSE,
				    &do_forward);
    }

    krb5_free_principal(context, server);
    krb5_data_free(&cksum_data);

    if (status) {
	if(status == KRB5_SENDAUTH_REJECTED &&
	   protocol_version == 2 && protocol_version_str == NULL)
	    sendauth_version_error = 1;
	else
	    krb5_warn(context, status, "%s", hostname);
	return 1;
    }

    status = krb5_auth_con_getlocalsubkey (context, auth_context, &keyblock);
    if(keyblock == NULL)
	status = krb5_auth_con_getkey (context, auth_context, &keyblock);
    if (status) {
	warnx ("krb5_auth_con_getkey: %s", krb5_get_err_text(context, status));
	return 1;
    }

    status = krb5_auth_con_setaddrs_from_fd (context,
					     auth_context,
					     &s);
    if (status) {
        warnx("krb5_auth_con_setaddrs_from_fd: %s",
	      krb5_get_err_text(context, status));
        return(1);
    }

    status = krb5_crypto_init(context, keyblock, 0, &crypto);
    if(status) {
	warnx ("krb5_crypto_init: %s", krb5_get_err_text(context, status));
	return 1;
    }

    len = strlen(remote_user) + 1;
    if (net_write (s, remote_user, len) != len) {
	warn ("write");
	return 1;
    }
    if (do_encrypt && net_write (s, "-x ", 3) != 3) {
	warn ("write");
	return 1;
    }
    if (net_write (s, cmd, cmd_len) != cmd_len) {
	warn ("write");
	return 1;
    }

    if (do_unique_tkfile) {
	if (net_write (s, tkfile, strlen(tkfile)) != strlen(tkfile)) {
	    warn ("write");
	    return 1;
	}
    }
    len = strlen(local_user) + 1;
    if (net_write (s, local_user, len) != len) {
	warn ("write");
	return 1;
    }

    if (!do_forward
	|| krb5_forward_cred (auth_context, s, hostname, do_forwardable)) {
	/* Empty forwarding info */

	u_char zero[4] = {0, 0, 0, 0};
	write (s, &zero, 4);
    }
    krb5_auth_con_free (context, auth_context);
    return 0;
}
/*
 * 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);
}
Esempio n. 11
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_recvauth_match_version(krb5_context context,
			    krb5_auth_context *auth_context,
			    krb5_pointer p_fd,
			    krb5_boolean (*match_appl_version)(const void *, 
							       const char*),
			    const void *match_data,
			    krb5_principal server,
			    int32_t flags,
			    krb5_keytab keytab,
			    krb5_ticket **ticket)
{
  krb5_error_code ret;
  const char *version = KRB5_SENDAUTH_VERSION;
  char her_version[sizeof(KRB5_SENDAUTH_VERSION)];
  char *her_appl_version;
  u_int32_t len;
  u_char repl;
  krb5_data data;
  krb5_flags ap_options;
  ssize_t n;

  /*
   * If there are no addresses in auth_context, get them from `fd'.
   */

  if (*auth_context == NULL) {
      ret = krb5_auth_con_init (context, auth_context);
      if (ret)
	  return ret;
  }

  ret = krb5_auth_con_setaddrs_from_fd (context,
					*auth_context,
					p_fd);
  if (ret)
      return ret;

  if(!(flags & KRB5_RECVAUTH_IGNORE_VERSION)) {
    n = krb5_net_read (context, p_fd, &len, 4);
    if (n < 0) {
	ret = errno;
	krb5_set_error_string (context, "read: %s", strerror(errno));
	return ret;
    }
    if (n == 0) {
	krb5_clear_error_string (context);
	return KRB5_SENDAUTH_BADAUTHVERS;
    }
    len = ntohl(len);
    if (len != sizeof(her_version)
	|| krb5_net_read (context, p_fd, her_version, len) != len
	|| strncmp (version, her_version, len)) {
      repl = 1;
      krb5_net_write (context, p_fd, &repl, 1);
	krb5_clear_error_string (context);
      return KRB5_SENDAUTH_BADAUTHVERS;
    }
  }

  n = krb5_net_read (context, p_fd, &len, 4);
  if (n < 0) {
      ret = errno;
      krb5_set_error_string (context, "read: %s", strerror(errno));
      return ret;
  }
  if (n == 0) {
      krb5_clear_error_string (context);
      return KRB5_SENDAUTH_BADAPPLVERS;
  }
  len = ntohl(len);
  her_appl_version = malloc (len);
  if (her_appl_version == NULL) {
      repl = 2;
      krb5_net_write (context, p_fd, &repl, 1);
      krb5_set_error_string (context, "malloc: out of memory");
      return ENOMEM;
  }
  if (krb5_net_read (context, p_fd, her_appl_version, len) != len
      || !(*match_appl_version)(match_data, her_appl_version)) {
    repl = 2;
    krb5_net_write (context, p_fd, &repl, 1);
    krb5_set_error_string (context, "wrong sendauth version (%s)",
			   her_appl_version);
    free (her_appl_version);
    return KRB5_SENDAUTH_BADAPPLVERS;
  }
  free (her_appl_version);

  repl = 0;
  if (krb5_net_write (context, p_fd, &repl, 1) != 1) {
    ret = errno;
    krb5_set_error_string (context, "write: %s", strerror(errno));
    return ret;
  }

  krb5_data_zero (&data);
  ret = krb5_read_message (context, p_fd, &data);
  if (ret)
      return ret;

  ret = krb5_rd_req (context,
		     auth_context,
		     &data,
		     server,
		     keytab,
		     &ap_options,
		     ticket);
  krb5_data_free (&data);
  if (ret) {
      krb5_data error_data;
      krb5_error_code ret2;

      ret2 = krb5_mk_error (context,
			    ret,
			    NULL,
			    NULL,
			    NULL,
			    server,
			    NULL,
			    NULL,
			    &error_data);
      if (ret2 == 0) {
	  krb5_write_message (context, p_fd, &error_data);
	  krb5_data_free (&error_data);
      }
      return ret;
  }      

  len = 0;
  if (krb5_net_write (context, p_fd, &len, 4) != 4) {
      ret = errno;
      krb5_set_error_string (context, "write: %s", strerror(errno));
      return ret;
  }

  if (ap_options & AP_OPTS_MUTUAL_REQUIRED) {
    ret = krb5_mk_rep (context, *auth_context, &data);
    if (ret)
      return ret;

    ret = krb5_write_message (context, p_fd, &data);
    if (ret)
	return ret;
    krb5_data_free (&data);
  }
  return 0;
}