Пример #1
0
static int
save_krb5_creds (int s,
                 krb5_auth_context auth_context,
                 krb5_principal client)

{
    int ret;
    krb5_data remote_cred;

    krb5_data_zero (&remote_cred);
    ret= krb5_read_message (context, (void *)&s, &remote_cred);
    if (ret) {
	krb5_data_free(&remote_cred);
	return 0;
    }
    if (remote_cred.length == 0)
	return 0;

    ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache);
    if (ret) {
	krb5_data_free(&remote_cred);
	return 0;
    }

    krb5_cc_initialize(context,ccache,client);
    ret = krb5_rd_cred2(context, auth_context, ccache, &remote_cred);
    if(ret != 0)
	syslog(LOG_INFO|LOG_AUTH,
	       "reading creds: %s", krb5_get_err_text(context, ret));
    krb5_data_free (&remote_cred);
    if (ret)
	return 0;
    return 1;
}
Пример #2
0
static OM_uint32
gsskrb5_accept_delegated_token
(OM_uint32 * minor_status,
 gsskrb5_ctx ctx,
 krb5_context context,
 gss_cred_id_t * delegated_cred_handle
    )
{
    krb5_ccache ccache = NULL;
    krb5_error_code kret;
    int32_t ac_flags, ret = GSS_S_COMPLETE;

    *minor_status = 0;

    /* XXX Create a new delegated_cred_handle? */
    if (delegated_cred_handle == NULL) {
	kret = krb5_cc_default (context, &ccache);
    } else {
	*delegated_cred_handle = NULL;
	kret = krb5_cc_new_unique (context, krb5_cc_type_memory,
				   NULL, &ccache);
    }
    if (kret) {
	ctx->flags &= ~GSS_C_DELEG_FLAG;
	goto out;
    }

    kret = krb5_cc_initialize(context, ccache, ctx->source);
    if (kret) {
	ctx->flags &= ~GSS_C_DELEG_FLAG;
	goto out;
    }

    krb5_auth_con_removeflags(context,
			      ctx->auth_context,
			      KRB5_AUTH_CONTEXT_DO_TIME,
			      &ac_flags);
    kret = krb5_rd_cred2(context,
			 ctx->auth_context,
			 ccache,
			 &ctx->fwd_data);
    krb5_auth_con_setflags(context,
			   ctx->auth_context,
			   ac_flags);
    if (kret) {
	ctx->flags &= ~GSS_C_DELEG_FLAG;
	ret = GSS_S_FAILURE;
	*minor_status = kret;
	goto out;
    }

    if (delegated_cred_handle) {
	gsskrb5_cred handle;

	ret = _gsskrb5_krb5_import_cred(minor_status,
					ccache,
					NULL,
					NULL,
					delegated_cred_handle);
	if (ret != GSS_S_COMPLETE)
	    goto out;

	handle = (gsskrb5_cred) *delegated_cred_handle;

	handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
	krb5_cc_close(context, ccache);
	ccache = NULL;
    }

out:
    if (ccache) {
	/* Don't destroy the default cred cache */
	if (delegated_cred_handle == NULL)
	    krb5_cc_close(context, ccache);
	else
	    krb5_cc_destroy(context, ccache);
    }
    return ret;
}
Пример #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;
    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;
	}
	
	{
	    char foo[2];
	    
	    foo[0] = ap->type;
	    foo[1] = ap->way;
	    
	    ret = krb5_verify_authenticator_checksum(context,
						     auth_context,
						     foo, 
						     sizeof(foo));

	    if (ret) {
		char *errbuf;
		asprintf(&errbuf, "Bad checksum: %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_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 (key_block == NULL) {
	    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;
	}
	if (key_block == NULL) {
	    Data(ap, KRB_REJECT, "no subkey received", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_getremotesubkey returned NULL key\r\n");
	    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 == ETYPE_DES_CBC_MD5 ||
	       key_block->keytype == ETYPE_DES_CBC_MD4 ||
	       key_block->keytype == ETYPE_DES_CBC_CRC) {
		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_REJECT);
	    krb5_free_keyblock_contents(context, key_block);
	    break;
	}
	auth_finished(ap, AUTH_USER);
	krb5_free_keyblock_contents(context, key_block);
	
	break;
    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;
	}

#if defined(DCE)
	esetenv("KRB5CCNAME", ccname, 1);
#endif
	ret = krb5_rd_cred2 (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);
#if defined(DCE)
	    dfsfwd = 1;
#endif
	}
	chown (ccname + 5, pwd->pw_uid, -1);
	if (auth_debug_mode)
	    printf("Forwarded credentials obtained\r\n");
	break;
    }
    default:
	if (auth_debug_mode)
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
	Data(ap, KRB_REJECT, 0, 0);
	break;
    }
}
Пример #4
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;
}
Пример #5
0
int
auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt)
{
	krb5_error_code problem;
	krb5_ccache ccache = NULL;
	char *pname;
	const char *errtxt;

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

	temporarily_use_uid(authctxt->pw);

	problem = krb5_cc_new_unique(authctxt->krb5_ctx, "FILE", NULL, &ccache);
	if (problem)
		goto fail;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
	    authctxt->krb5_user);
	if (problem)
		goto fail;

	problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
	    ccache, tgt);
	if (problem)
		goto fail;

	authctxt->krb5_fwd_ccache = ccache;
	ccache = NULL;

	authctxt->krb5_ticket_file = __UNCONST(krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache));

	problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
	    &pname);
	if (problem)
		goto fail;

#ifdef USE_PAM
	if (options.use_pam)
		do_pam_putenv(__UNCONST("KRB5CCNAME"), authctxt->krb5_ticket_file);
#endif
	debug("Kerberos v5 TGT accepted (%s)", pname);

	restore_uid();

	return (1);

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

	restore_uid();

	return (0);
}
int
auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt)
{
	krb5_error_code problem;
	krb5_ccache ccache = NULL;
	char *pname;
	krb5_creds **creds;

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

	temporarily_use_uid(authctxt->pw);

#ifdef HEIMDAL
	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache);
#else
{
	char ccname[40];
	int tmpfd;
	
	snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid());
	
	if ((tmpfd = mkstemp(ccname+strlen("FILE:")))==-1) {
		log("mkstemp(): %.100s", strerror(errno));
		problem = errno;
		goto fail;
	}
	if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
		log("fchmod(): %.100s", strerror(errno));
		close(tmpfd);
		problem = errno;
		goto fail;
	}
	close(tmpfd);
	problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &ccache);
}
#endif
	if (problem)
		goto fail;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
	    authctxt->krb5_user);
	if (problem)
		goto fail;

#ifdef HEIMDAL
	problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
	    ccache, tgt);
	if (problem)
		goto fail;
#else
	problem = krb5_rd_cred(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
	    tgt, &creds, NULL);
	if (problem)
		goto fail;
	problem = krb5_cc_store_cred(authctxt->krb5_ctx, ccache, *creds);
	if (problem)
		goto fail;
#endif

	authctxt->krb5_fwd_ccache = ccache;
	ccache = NULL;

	authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);

	problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
	    &pname);
	if (problem)
		goto fail;

	debug("Kerberos v5 TGT accepted (%s)", pname);

	restore_uid();

	return (1);

 fail:
	if (problem)
		debug("Kerberos v5 TGT passing failed: %s",
		    krb5_get_err_text(authctxt->krb5_ctx, problem));
	if (ccache)
		krb5_cc_destroy(authctxt->krb5_ctx, ccache);

	restore_uid();

	return (0);
}