コード例 #1
0
ファイル: kerberos5.c プロジェクト: millken/zhuxianB30
int
kerberos5_is_auth (TN_Authenticator * ap, unsigned char *data, int cnt,
		   char *errbuf, int errbuflen)
{
  int r = 0;
  krb5_keytab keytabid = 0;
  krb5_authenticator *authenticator;
  char *name;
  krb5_data outbuf;
  krb5_keyblock *newkey = NULL;
  krb5_principal server;

# ifdef ENCRYPTION
  Session_Key skey;
# endif

  auth.data = (char *) data;
  auth.length = cnt;

  if (!r && !auth_context)
    r = krb5_auth_con_init (telnet_context, &auth_context);
  if (!r)
    {
      krb5_rcache rcache;

      r = krb5_auth_con_getrcache (telnet_context, auth_context, &rcache);
      if (!r && !rcache)
	{
	  r = krb5_sname_to_principal (telnet_context, 0, 0,
				       KRB5_NT_SRV_HST, &server);
	  if (!r)
	    {
	      r = krb5_get_server_rcache (telnet_context,
					  krb5_princ_component
					  (telnet_context, server, 0),
					  &rcache);
	      krb5_free_principal (telnet_context, server);
	    }
	}
      if (!r)
	r = krb5_auth_con_setrcache (telnet_context, auth_context, rcache);
    }

  if (!r && telnet_srvtab)
    r = krb5_kt_resolve (telnet_context, telnet_srvtab, &keytabid);
  if (!r)
    r = krb5_rd_req (telnet_context, &auth_context, &auth,
		     NULL, keytabid, NULL, &ticket);
  if (r)
    {
      snprintf (errbuf, errbuflen, "krb5_rd_req failed: %s",
		error_message (r));
      return r;
    }

  /* 256 bytes should be much larger than any reasonable
     first component of a service name especially since
     the default is of length 4. */
  if (krb5_princ_component (telnet_context, ticket->server, 0)->length < 256)
    {
      char princ[256];
      strncpy (princ,
	       krb5_princ_component (telnet_context, ticket->server, 0)->data,
	       krb5_princ_component (telnet_context, ticket->server,
				     0)->length);
      princ[krb5_princ_component (telnet_context, ticket->server, 0)->
	    length] = '\0';
      if (strcmp ("host", princ))
	{
	  snprintf (errbuf, errbuflen,
		    "incorrect service name: \"%s\" != \"host\"", princ);
	  return 1;
	}
    }
  else
    {
      strncpy (errbuf, "service name too long", errbuflen);
      return 1;
    }

  r = krb5_auth_con_getauthenticator (telnet_context,
				      auth_context, &authenticator);
  if (r)
    {
      snprintf (errbuf, errbuflen,
		"krb5_auth_con_getauthenticator failed: %s",
		error_message (r));
      return 1;
    }

# ifdef AUTH_ENCRYPT_MASK
  if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON
      && !authenticator->checksum)
    {
      snprintf (errbuf, errbuflen,
		"authenticator is missing required checksum");
      return 1;
    }
# endif

  if (authenticator->checksum)
    {
      char type_check[2];
      krb5_checksum *cksum = authenticator->checksum;
      krb5_keyblock *key;

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

      r = krb5_auth_con_getkey (telnet_context, auth_context, &key);
      if (r)
	{
	  snprintf (errbuf, errbuflen,
		    "krb5_auth_con_getkey failed: %s", error_message (r));
	  return 1;
	}

      r = krb5_verify_checksum (telnet_context,
				cksum->checksum_type, cksum,
				&type_check, 2, key->contents, key->length);

      if (r)
	{
	  snprintf (errbuf, errbuflen,
		    "checksum verification failed: %s", error_message (r));
	  return 1;
	}
      krb5_free_keyblock (telnet_context, key);
    }

  krb5_free_authenticator (telnet_context, authenticator);
  if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
    {
      if ((r = krb5_mk_rep (telnet_context, auth_context, &outbuf)))
	{
	  snprintf (errbuf, errbuflen, "Make reply failed: %s",
		    error_message (r));
	  return 1;
	}

      Data (ap, KRB_RESPONSE, outbuf.data, outbuf.length);
    }

  if (krb5_unparse_name (telnet_context, ticket->enc_part2->client, &name))
    name = 0;

  Data (ap, KRB_ACCEPT, name, name ? -1 : 0);
  DEBUG (("telnetd: Kerberos5 identifies him as ``%s''\r\n",
	  name ? name : ""));
  auth_finished (ap, AUTH_USER);

  free (name);
  krb5_auth_con_getremotesubkey (telnet_context, auth_context, &newkey);

  if (session_key)
    {
      krb5_free_keyblock (telnet_context, session_key);
      session_key = 0;
    }

  if (newkey)
    {
      krb5_copy_keyblock (telnet_context, newkey, &session_key);
      krb5_free_keyblock (telnet_context, newkey);
    }
  else
    {
      krb5_copy_keyblock (telnet_context, ticket->enc_part2->session,
			  &session_key);
    }
  telnet_encrypt_key (&skey);
  return 0;
}
コード例 #2
0
ファイル: ipa-getkeytab.c プロジェクト: icute1349/freeipa
int main(int argc, const char *argv[])
{
	static const char *server = NULL;
	static const char *principal = NULL;
	static const char *keytab = NULL;
	static const char *enctypes_string = NULL;
	static const char *binddn = NULL;
	static const char *bindpw = NULL;
	int quiet = 0;
	int askpass = 0;
	int permitted_enctypes = 0;
	int retrieve = 0;
        struct poptOption options[] = {
            { "quiet", 'q', POPT_ARG_NONE, &quiet, 0,
              _("Print as little as possible"), _("Output only on errors")},
            { "server", 's', POPT_ARG_STRING, &server, 0,
              _("Contact this specific KDC Server"),
              _("Server Name") },
            { "principal", 'p', POPT_ARG_STRING, &principal, 0,
              _("The principal to get a keytab for (ex: ftp/[email protected])"),
              _("Kerberos Service Principal Name") },
            { "keytab", 'k', POPT_ARG_STRING, &keytab, 0,
              _("File were to store the keytab information"),
              _("Keytab File Name") },
	    { "enctypes", 'e', POPT_ARG_STRING, &enctypes_string, 0,
              _("Encryption types to request"),
              _("Comma separated encryption types list") },
	    { "permitted-enctypes", 0, POPT_ARG_NONE, &permitted_enctypes, 0,
              _("Show the list of permitted encryption types and exit"),
              _("Permitted Encryption Types") },
	    { "password", 'P', POPT_ARG_NONE, &askpass, 0,
              _("Asks for a non-random password to use for the principal"), NULL },
	    { "binddn", 'D', POPT_ARG_STRING, &binddn, 0,
              _("LDAP DN"), _("DN to bind as if not using kerberos") },
	    { "bindpw", 'w', POPT_ARG_STRING, &bindpw, 0,
              _("LDAP password"), _("password to use if not using kerberos") },
	    { "retrieve", 'r', POPT_ARG_NONE, &retrieve, 0,
              _("Retrieve current keys without changing them"), NULL },
            POPT_AUTOHELP
            POPT_TABLEEND
	};
	poptContext pc;
	char *ktname;
	char *password = NULL;
	krb5_context krbctx;
	krb5_ccache ccache;
	krb5_principal uprinc = NULL;
	krb5_principal sprinc;
	krb5_error_code krberr;
	struct keys_container keys = { 0 };
	krb5_keytab kt;
	int kvno;
	int i, ret;
	char *err_msg;

    ret = init_gettext();
    if (ret) {
        fprintf(stderr, "Failed to load translations\n");
    }

	krberr = krb5_init_context(&krbctx);
	if (krberr) {
		fprintf(stderr, _("Kerberos context initialization failed\n"));
		exit(1);
	}

	pc = poptGetContext("ipa-getkeytab", argc, (const char **)argv, options, 0);
	ret = poptGetNextOpt(pc);
	if (ret == -1 && permitted_enctypes &&
	    !(server || principal || keytab || quiet)) {
		krb5_enctype *ktypes;
		char enc[79]; /* fit std terminal or truncate */

		krberr = krb5_get_permitted_enctypes(krbctx, &ktypes);
		if (krberr) {
			fprintf(stderr, _("No system preferred enctypes ?!\n"));
			exit(1);
		}
		fprintf(stdout, _("Supported encryption types:\n"));
		for (i = 0; ktypes[i]; i++) {
			krberr = krb5_enctype_to_string(ktypes[i], enc, 79);
			if (krberr) {
				fprintf(stderr, _("Warning: "
                                        "failed to convert type (#%d)\n"), i);
				continue;
			}
			fprintf(stdout, "%s\n", enc);
		}
		ipa_krb5_free_ktypes(krbctx, ktypes);
		exit (0);
	}

	if (ret != -1 || !principal || !keytab || permitted_enctypes) {
		if (!quiet) {
			poptPrintUsage(pc, stderr, 0);
		}
		exit(2);
	}

	if (NULL!=binddn && NULL==bindpw) {
		fprintf(stderr,
                        _("Bind password required when using a bind DN.\n"));
		if (!quiet)
			poptPrintUsage(pc, stderr, 0);
		exit(10);
	}

    if (!server) {
        struct ipa_config *ipacfg = NULL;

        ret = read_ipa_config(&ipacfg);
        if (ret == 0) {
            server = ipacfg->server_name;
            ipacfg->server_name = NULL;
        }
        free(ipacfg);
        if (!server) {
            fprintf(stderr, _("Server name not provided and unavailable\n"));
            exit(2);
        }
    }

    if (askpass && retrieve) {
        fprintf(stderr, _("Incompatible options provided (-r and -P)\n"));
        exit(2);
    }

        if (askpass) {
		password = ask_password(krbctx);
		if (!password) {
			exit(2);
		}
	} else if (enctypes_string && strchr(enctypes_string, ':')) {
		if (!quiet) {
			fprintf(stderr, _("Warning: salt types are not honored"
                                " with randomized passwords (see opt. -P)\n"));
		}
	}

	ret = asprintf(&ktname, "WRFILE:%s", keytab);
	if (ret == -1) {
		exit(3);
	}

	krberr = krb5_parse_name(krbctx, principal, &sprinc);
	if (krberr) {
		fprintf(stderr, _("Invalid Service Principal Name\n"));
		exit(4);
	}

	if (NULL == bindpw) {
		krberr = krb5_cc_default(krbctx, &ccache);
		if (krberr) {
			fprintf(stderr,
                                _("Kerberos Credential Cache not found. "
				  "Do you have a Kerberos Ticket?\n"));
			exit(5);
		}

		krberr = krb5_cc_get_principal(krbctx, ccache, &uprinc);
		if (krberr) {
			fprintf(stderr,
                                _("Kerberos User Principal not found. "
				  "Do you have a valid Credential Cache?\n"));
			exit(6);
		}
	}

	krberr = krb5_kt_resolve(krbctx, ktname, &kt);
	if (krberr) {
		fprintf(stderr, _("Failed to open Keytab\n"));
		exit(7);
	}

    kvno = -1;
    ret = ldap_get_keytab(krbctx, (retrieve == 0), password, enctypes_string,
                          server, principal, uprinc, binddn, bindpw,
                          &keys, &kvno, &err_msg);
    if (ret) {
        if (!quiet && err_msg != NULL) {
            fprintf(stderr, "%s", err_msg);
        }
    }

    if (retrieve == 0 && kvno == -1) {
        if (!quiet) {
            fprintf(stderr,
                    _("Retrying with pre-4.0 keytab retrieval method...\n"));
        }

        /* create key material */
        ret = create_keys(krbctx, sprinc, password, enctypes_string, &keys, &err_msg);
        if (!ret) {
            if (err_msg != NULL) {
                fprintf(stderr, "%s", err_msg);
            }

            fprintf(stderr, _("Failed to create key material\n"));
            exit(8);
        }

        kvno = ldap_set_keytab(krbctx, server, principal, uprinc, binddn, bindpw, &keys);
    }

    if (kvno == -1) {
        fprintf(stderr, _("Failed to get keytab\n"));
        exit(9);
    }

	for (i = 0; i < keys.nkeys; i++) {
		krb5_keytab_entry kt_entry;
		memset((char *)&kt_entry, 0, sizeof(kt_entry));
		kt_entry.principal = sprinc;
		kt_entry.key = keys.ksdata[i].key;
		kt_entry.vno = kvno;

		krberr = krb5_kt_add_entry(krbctx, kt, &kt_entry);
		if (krberr) {
			fprintf(stderr,
                                _("Failed to add key to the keytab\n"));
			exit (11);
		}
	}

	free_keys_contents(krbctx, &keys);

	krberr = krb5_kt_close(krbctx, kt);
	if (krberr) {
		fprintf(stderr, _("Failed to close the keytab\n"));
		exit (12);
	}

	if (!quiet) {
		fprintf(stderr,
			_("Keytab successfully retrieved and stored in: %s\n"),
			keytab);
	}
	exit(0);
}
コード例 #3
0
ファイル: kinit.c プロジェクト: aosm/Heimdal
static krb5_error_code
get_new_tickets(krb5_context context,
		krb5_principal principal,
		krb5_ccache ccache,
		krb5_deltat ticket_life,
		int interactive)
{
    krb5_error_code ret;
    krb5_get_init_creds_opt *opt;
    krb5_creds cred;
    char passwd[256];
    krb5_deltat start_time = 0;
    krb5_deltat renew = 0;
    const char *renewstr = NULL;
    krb5_enctype *enctype = NULL;
    krb5_ccache tempccache;
    krb5_init_creds_context icc;
    krb5_keytab kt = NULL;
    int will_use_keytab =  (use_keytab || keytab_str);
    krb5_prompter_fct prompter = NULL;
    int need_prompt;

    passwd[0] = '\0';

    if (password_file) {
	FILE *f;

	if (strcasecmp("STDIN", password_file) == 0)
	    f = stdin;
	else
	    f = fopen(password_file, "r");
	if (f == NULL)
	    krb5_errx(context, 1, "Failed to open the password file %s",
		      password_file);

	if (fgets(passwd, sizeof(passwd), f) == NULL)
	    krb5_errx(context, 1,
		      N_("Failed to read password from file %s", ""),
		      password_file);
	if (f != stdin)
	    fclose(f);
	passwd[strcspn(passwd, "\n")] = '\0';
    }

#if defined(__APPLE__) && !defined(__APPLE_TARGET_EMBEDDED__)
    if (passwd[0] == '\0' && !will_use_keytab && home_directory_flag) {
	const char *realm;
	OSStatus osret;
	UInt32 length;
	void *buffer;
	char *name;

	realm = krb5_principal_get_realm(context, principal);

	ret = krb5_unparse_name_flags(context, principal,
				      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
	if (ret)
	    goto nopassword;

	osret = SecKeychainFindGenericPassword(NULL, (UInt32)strlen(realm), realm,
					       (UInt32)strlen(name), name,
					       &length, &buffer, &passwordItem);
	free(name);
	if (osret != noErr)
	    goto nopassword;

	if (length < sizeof(passwd) - 1) {
	    memcpy(passwd, buffer, length);
	    passwd[length] = '\0';
	}
	SecKeychainItemFreeContent(NULL, buffer);
    nopassword:
	do { } while(0);
    }
#endif

    need_prompt = !(pk_user_id || ent_user_id || anonymous_flag || will_use_keytab || passwd[0] != '\0') && interactive;
    if (need_prompt)
	prompter = krb5_prompter_posix;
    else
	prompter = krb5_prompter_print_only;

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

    ret = krb5_get_init_creds_opt_alloc (context, &opt);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    krb5_get_init_creds_opt_set_default_flags(context, "kinit",
	krb5_principal_get_realm(context, principal), opt);

    if(forwardable_flag != -1)
	krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag);

    if(proxiable_flag != -1)
	krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag);
    if(anonymous_flag)
	krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag);
    if (pac_flag != -1)
	krb5_get_init_creds_opt_set_pac_request(context, opt,
						pac_flag ? TRUE : FALSE);
    if (canonicalize_flag)
	krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE);
    if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag)
	krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
    if (pk_user_id || ent_user_id || anonymous_flag) {
	ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
						 principal,
						 pk_user_id,
						 pk_x509_anchors,
						 NULL,
						 NULL,
						 pk_use_enckey ? 2 : 0 |
						 anonymous_flag ? 4 : 0,
						 interactive ? krb5_prompter_posix : krb5_prompter_print_only,
						 NULL,
						 passwd);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
	if (ent_user_id)
	    krb5_get_init_creds_opt_set_pkinit_user_cert(context, opt, ent_user_id);
    }

    if (addrs_flag != -1)
	krb5_get_init_creds_opt_set_addressless(context, opt,
						addrs_flag ? FALSE : TRUE);

    if (renew_life == NULL && renewable_flag)
	renewstr = "1 month";
    if (renew_life)
	renewstr = renew_life;
    if (renewstr) {
	renew = parse_time (renewstr, "s");
	if (renew < 0)
	    errx (1, "unparsable time: %s", renewstr);

	krb5_get_init_creds_opt_set_renew_life (opt, renew);
    }

    if(ticket_life != 0)
	krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life);

    if(start_str) {
	int tmp = parse_time (start_str, "s");
	if (tmp < 0)
	    errx (1, N_("unparsable time: %s", ""), start_str);

	start_time = tmp;
    }

    if(etype_str.num_strings) {
	int i;

	enctype = malloc(etype_str.num_strings * sizeof(*enctype));
	if(enctype == NULL)
	    errx(1, "out of memory");
	for(i = 0; i < etype_str.num_strings; i++) {
	    ret = krb5_string_to_enctype(context,
					 etype_str.strings[i],
					 &enctype[i]);
	    if(ret)
		krb5_err(context, 1, ret, "unrecognized enctype: %s",
			 etype_str.strings[i]);
	}
	krb5_get_init_creds_opt_set_etype_list(opt, enctype,
					       etype_str.num_strings);
    }

    ret = krb5_init_creds_init(context, principal,
			       prompter, NULL,
			       start_time, opt, &icc);
    if (ret)
	krb5_err (context, 1, ret, "krb5_init_creds_init");

    if (server_str) {
	ret = krb5_init_creds_set_service(context, icc, server_str);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_init_creds_set_service");
    }

    if (kdc_hostname)
	krb5_init_creds_set_kdc_hostname(context, icc, kdc_hostname);

    if (fast_armor_cache_string) {
	krb5_ccache fastid;
	
	ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve(FAST cache)");
	
	ret = krb5_init_creds_set_fast_ccache(context, icc, fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_fast_ccache");
    }

    if(will_use_keytab) {
	if(keytab_str)
	    ret = krb5_kt_resolve(context, keytab_str, &kt);
	else
	    ret = krb5_kt_default(context, &kt);
	if (ret)
	    krb5_err (context, 1, ret, "resolving keytab");

	ret = krb5_init_creds_set_keytab(context, icc, kt);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_init_creds_set_keytab");
    }

    if (passwd[0] == '\0' && need_prompt) {
	char *p, *prompt;

	krb5_unparse_name(context, principal, &p);
	asprintf (&prompt, N_("%s's Password: "******""), p);
	free(p);

	if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
	    memset(passwd, 0, sizeof(passwd));
	    errx(1, "failed to read password");
	}
	free (prompt);
    }

    if (passwd[0]) {
	ret = krb5_init_creds_set_password(context, icc, passwd);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_password");
    }

    ret = krb5_init_creds_get(context, icc);

#ifdef __APPLE__
    /*
     * Save password in Keychain
     */
    if (ret == 0 && keychain_flag && passwordItem == NULL) {
	krb5_error_code ret2;
	const char *realm;
	char *name;

	realm = krb5_principal_get_realm(context, principal);
	ret2 = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
	if (ret2 == 0) {
	    (void)SecKeychainAddGenericPassword(NULL,
						(UInt32)strlen(realm), realm,
						(UInt32)strlen(name), name,
						(UInt32)strlen(passwd), passwd,
						NULL);
	    free(name);
	}
    }
#endif

    memset(passwd, 0, sizeof(passwd));

    switch(ret){
    case 0:
	break;
    case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */
	exit(1);
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KRB_AP_ERR_MODIFIED:
    case KRB5KDC_ERR_PREAUTH_FAILED:
    case KRB5_GET_IN_TKT_LOOP:
#ifdef __APPLE__
	if (passwordItem)
	    SecKeychainItemDelete(passwordItem);
#endif
	krb5_errx(context, 1, N_("Password incorrect", ""));
    case KRB5KRB_AP_ERR_V4_REPLY:
	krb5_errx(context, 1, N_("Looks like a Kerberos 4 reply", ""));
    case KRB5KDC_ERR_KEY_EXPIRED:
	krb5_errx(context, 1, N_("Password expired", ""));
    default:
	krb5_err(context, 1, ret, "krb5_get_init_creds");
    }

    ret = krb5_init_creds_get_creds(context, icc, &cred);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_get_creds");

    krb5_process_last_request(context, opt, icc);

    ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache),
			     NULL, &tempccache);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_new_unique");

    ret = krb5_init_creds_store(context, icc, tempccache);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_store");

    ret = krb5_init_creds_store_config(context, icc, tempccache);
    if (ret)
	krb5_warn(context, ret, "krb5_init_creds_store_config");

    ret = krb5_init_creds_warn_user(context, icc);
    if (ret)
	krb5_warn(context, ret, "krb5_init_creds_warn_user");

#ifdef __APPLE__
    /*
     * Set for this case, default to * so that all processes can use
     * this cache.
     */
    {
	heim_array_t bundleacl = heim_array_create();
	heim_string_t ace;

	if (bundle_acl_strings.num_strings > 0) {
	    int i;
	    for (i = 0; i < bundle_acl_strings.num_strings; i++) {
		ace = heim_string_create(bundle_acl_strings.strings[i]);
		heim_array_append_value(bundleacl, ace);
		heim_release(ace);
	    }
	} else {
	    ace = heim_string_create("*");
	    heim_array_append_value(bundleacl, ace);
	    heim_release(ace);
	}
	krb5_cc_set_acl(context, tempccache, "kHEIMAttrBundleIdentifierACL", bundleacl);
	heim_release(bundleacl);
    }
#endif

    ret = krb5_cc_move(context, tempccache, ccache);
    if (ret) {
	(void)krb5_cc_destroy(context, tempccache);
	krb5_err (context, 1, ret, "krb5_cc_move");
    }

    if (switch_cache_flags)
	krb5_cc_switch(context, ccache);

    if (ok_as_delegate_flag || windows_flag || use_referrals_flag) {
	unsigned char d = 0;
	krb5_data data;

	if (ok_as_delegate_flag || windows_flag)
	    d |= 1;
	if (use_referrals_flag || windows_flag)
	    d |= 2;

	data.length = 1;
	data.data = &d;

	krb5_cc_set_config(context, ccache, NULL, "realm-config", &data);
    }

    if (enctype)
	free(enctype);

    krb5_init_creds_free(context, icc);
    krb5_get_init_creds_opt_free(context, opt);

    if (kt)
	krb5_kt_close(context, kt);

#ifdef __APPLE__
    if (passwordItem)
	CFRelease(passwordItem);
#endif

    return 0;
}
コード例 #4
0
//----------------------------------------------------------------------
// Authenticate to server as a daemon (i.e. using the keytab)
//----------------------------------------------------------------------
int Condor_Auth_Kerberos :: init_daemon()
{
    int            code, rc = TRUE;
    priv_state     priv;

    char *         daemonPrincipal = 0;

    krb5_keytab    keytab = 0;

	// init some member vars
    creds_ = (krb5_creds *) malloc(sizeof(krb5_creds));
    keytabName_ = param(STR_KERBEROS_SERVER_KEYTAB);

	// needed for extracting service name
	char * tmpsname = 0;
	MyString sname;

    memset(creds_, 0, sizeof(krb5_creds));

    //------------------------------------------
    // Initialize the principal for daemon (properly :-)
    //------------------------------------------
	// this means using a keytab to obtain a tgt.
	//
	// in krb5-1.2 and earlier this was done with krb5_get_in_tkt_keytab()
	//
	// in krb5-1.3 and
	// later this should be done with krb5_get_init_creds_keytab

	// select a server principal
    daemonPrincipal = param(STR_KERBEROS_SERVER_PRINCIPAL);

	if (daemonPrincipal) {
		// it was defined explicitly in the config file
		if ((code = krb5_parse_name(krb_context_, daemonPrincipal, &krb_principal_))) {
			free(daemonPrincipal);
			goto error;
		}
	} else {
		// not defined in config, let's construct one from a service name
		daemonPrincipal = param(STR_KERBEROS_SERVER_SERVICE);
		if (!daemonPrincipal) {
			// use the host credential if no service was specified
			daemonPrincipal = strdup(STR_DEFAULT_CONDOR_SERVICE);
		}

    	if ((code = krb5_sname_to_principal(krb_context_, 
                                        	NULL, 
                                        	daemonPrincipal,
                                        	KRB5_NT_SRV_HST, 
                                        	&krb_principal_))) {
			free(daemonPrincipal);
			goto error;
		}
	}
	free(daemonPrincipal);
	daemonPrincipal = 0;

   
	dprintf_krb5_principal( D_SECURITY, "init_daemon: client principal is '%s'\n", krb_principal_);

    if (keytabName_) {
    	dprintf(D_SECURITY, "init_daemon: Using keytab %s\n", keytabName_);
        code = krb5_kt_resolve(krb_context_, keytabName_, &keytab);
    } else {
		char defktname[_POSIX_PATH_MAX];
		krb5_kt_default_name(krb_context_, defktname, _POSIX_PATH_MAX);
    	dprintf(D_SECURITY, "init_daemon: Using default keytab %s\n", defktname);
        code = krb5_kt_default(krb_context_, &keytab);
    }
	if (code) {
		goto error;
	}

	// get the service name out of the member variable server_
	tmpsname = 0;
	code = krb5_unparse_name(krb_context_, server_, &tmpsname);
	if (code) {
		goto error;
	}

	// copy it into a mystring for stack cleanup purposes
	sname = tmpsname;
	free (tmpsname);

	dprintf(D_SECURITY, "init_daemon: Trying to get tgt credential for service %s\n", sname.Value());

	priv = set_root_priv();   // Get the old privilige
	code = krb5_get_init_creds_keytab(krb_context_, creds_, krb_principal_, keytab, 0, const_cast<char*>(sname.Value()), 0);
	set_priv(priv);
	if(code) {
		goto error;
	}

	dprintf_krb5_principal( D_SECURITY, "init_daemon: gic_kt creds_->client is '%s'\n", creds_->client );
	dprintf_krb5_principal( D_SECURITY, "init_daemon: gic_kt creds_->server is '%s'\n", creds_->server );

    dprintf(D_SECURITY, "Success..........................\n");
    
    rc = TRUE;

    goto cleanup;
    
 error:
    
    dprintf(D_ALWAYS, "AUTH_ERROR: %s\n", error_message(code));

    rc = FALSE;
    
 cleanup:
    
    if (keytab) {
        krb5_kt_close(krb_context_, keytab);   
    }
    
    return rc;
}
コード例 #5
0
ファイル: curl_gssapi.c プロジェクト: Khalian/curl
OM_uint32 Curl_gss_init_sec_context(
    struct connectdata *conn,
    OM_uint32 * minor_status,
    gss_ctx_id_t * context,
    gss_name_t target_name,
    gss_channel_bindings_t input_chan_bindings,
    gss_buffer_t input_token,
    gss_buffer_t output_token,
    OM_uint32 * ret_flags)
{ 
	krb5_context krb_context = NULL;							/* Kerberos context object */
	krb5_ccache ccache = NULL;									
    krb5_creds creds;
    krb5_get_init_creds_opt *opts = NULL;
    krb5_principal principal = NULL;
    krb5_keytab ktab = NULL;
	OM_uint32 min_stat, maj_stat;
	char *cachename = NULL;
    char *keytabfile = "";
	OM_uint32 major_status;

	struct SessionHandle *data = conn->data;
	int ret;
	OM_uint32 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
	conn->data->curl_gss_creds = GSS_C_NO_CREDENTIAL;
	
	memset(&creds, 0, sizeof(creds));

	if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) {
		#ifdef GSS_C_DELEG_POLICY_FLAG
			req_flags |= GSS_C_DELEG_POLICY_FLAG;
		#else
		    infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
		        "compiled in\n");
		#endif
	}

	if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG)
		req_flags |= GSS_C_DELEG_FLAG;

	if((ret = krb5_init_context(&krb_context)) != 0) {
		 curl_krb5_print_error_message(krb_context, ret, data);
		 curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		 return CURLE_KERBEROS_AUTH_FAILED;
	}
  
	if ((ret = krb5_parse_name(krb_context, conn->user, &principal)) != 0) {
		 curl_krb5_print_error_message(krb_context, ret, data);
		 curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		 return CURLE_KERBEROS_AUTH_FAILED;
	}
	
	if ((ret = krb5_get_init_creds_opt_alloc (krb_context , &opts)) != 0) {
         curl_krb5_print_error_message(krb_context, ret, data);
		 curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
	     return CURLE_KERBEROS_AUTH_FAILED;
	}  

	if (conn->bits.user_keytab) {
		 infof(data, "KRB5_DATA: Keytab location is %s \n", conn->keytab_location);
		 if ((ret = krb5_kt_resolve(krb_context, conn->keytab_location, &ktab)) != 0) {
			curl_krb5_print_error_message(krb_context, ret, data);
			curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		    return CURLE_KERBEROS_AUTH_FAILED;
		 }
		 if ((ret = krb5_get_init_creds_keytab(krb_context, &creds, principal, ktab, 0, NULL, opts)) != 0) {
			 curl_krb5_print_error_message(krb_context, ret, data);
			 curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		     return CURLE_KERBEROS_AUTH_FAILED;
		 }
    } else if(conn->bits.user_passwd) {
		  infof(data,"KRB5_DATA: Using the user password method \n");
		  if ((ret = krb5_get_init_creds_password(krb_context,&creds,principal,conn->passwd,NULL,NULL,0,NULL,opts)) != 0 ) {
				curl_krb5_print_error_message(krb_context, ret, data);
				curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
				return CURLE_KERBEROS_AUTH_FAILED;
		  }
	} else if(conn->bits.credential_cache) {
		infof(data, "Resolving given credential cache \n");
		infof(data, "KRB5_DATA: Credential cache location is %s \n", conn->credential_cache);
		if ((ret = krb5_cc_resolve(krb_context, conn->credential_cache, &ccache))!=0) {
			   curl_krb5_print_error_message(krb_context, ret, data);
			   curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
			   return CURLE_KERBEROS_AUTH_FAILED;
		}
	} else if(conn->data->isIntermediateServer) {
		infof(data, "KRB5_DATA: Curl is carrying a gss credential \n");
		major_status = gss_init_sec_context(minor_status,
                              conn->data->deleg_gss_creds, /* cred_handle */
                              context,
                              target_name,
                              GSS_C_NO_OID, /* mech_type */
                              req_flags,
                              0, /* time_req */
                              input_chan_bindings,
                              input_token,
                              NULL, /* actual_mech_type */
                              output_token,
                              ret_flags,
                              NULL /* time_rec */);
		curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		return major_status;
	} else {		
	      infof(data, "KRB5_DATA: Passed no password/keytab location, using default credentials\n ");
		  conn->data->curl_gss_creds = GSS_C_NO_CREDENTIAL;
		  major_status = gss_init_sec_context(minor_status,
                              conn->data->curl_gss_creds, /* cred_handle */
                              context,
                              target_name,
                              GSS_C_NO_OID, /* mech_type */
                              req_flags,
                              0, /* time_req */
                              input_chan_bindings,
                              input_token,
                              NULL, /* actual_mech_type */
                              output_token,
                              ret_flags,
                              NULL /* time_rec */);
		  curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		  return major_status;
    }
	if(!conn->bits.credential_cache) {
		infof(data, "Creating new credential cache, since none specified \n");
		if((ret = krb5_cc_new_unique( krb_context, "MEMORY", NULL, &ccache)) != 0) {
			 curl_krb5_print_error_message(krb_context, ret, data);
			 curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);
			 return CURLE_KERBEROS_AUTH_FAILED;
		}
		infof(data, "Initializing credential cache \n");
		if ((ret = krb5_cc_initialize(krb_context, ccache, principal))!=0) {
		     curl_krb5_print_error_message(krb_context, ret, data);
			 curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);
			 return CURLE_KERBEROS_AUTH_FAILED;
		}
		infof(data, "Storing credential within credential cache \n");
		if ((ret = krb5_cc_store_cred(krb_context,ccache,&creds)) != 0) {
			 curl_krb5_print_error_message(krb_context, ret, data);
			 curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);
			 return CURLE_KERBEROS_AUTH_FAILED ;
		}
	}
	infof(data, "Attempting to import the credential \n");
	if ((maj_stat = gss_krb5_import_cred(&min_stat,
	    ccache,
		principal,
		NULL,
		&conn->data->curl_gss_creds))!=0) {
			  infof(data, "Importing krb5 credential into gss credentials failed\n");
			  curl_krb5_print_error_message(krb_context, min_stat, data);
			  if(conn->bits.credential_cache)
				  curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
			  else
				  curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);
			  return CURLE_KERBEROS_AUTH_FAILED;
		}

	infof(data, "Able to convert the credential \n");
	infof(data, "Attempting init sec context \n");

	major_status = gss_init_sec_context(minor_status,
                              conn->data->curl_gss_creds, /* cred_handle */
                              context,
                              target_name,
                              GSS_C_NO_OID, /* mech_type */
                              req_flags,
                              0, /* time_req */
                              input_chan_bindings,
                              input_token,
                              NULL, /* actual_mech_type */
                              output_token,
                              ret_flags,
                              NULL /* time_rec */);

	if(conn->bits.credential_cache)
        curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
    else
        curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);

	return major_status;
}
コード例 #6
0
ファイル: ipropd_master.c プロジェクト: DavidMulder/heimdal
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    void *kadm_handle;
    kadm5_server_context *server_context;
    kadm5_config_params conf;
    krb5_socket_t signal_fd, listen_fd;
    int log_fd;
    slave *slaves = NULL;
    uint32_t current_version = 0, old_version = 0;
    uint32_t current_tstamp = 0;
    krb5_keytab keytab;
    char **files;
    int aret;
    int optidx = 0;
    int restarter_fd = -1;
    struct stat st;

    setprogname(argv[0]);

    if (getarg(args, num_args, argc, argv, &optidx))
        krb5_std_usage(1, args, num_args);

    if (help_flag)
	krb5_std_usage(0, args, num_args);

    if (version_flag) {
	print_version(NULL);
	exit(0);
    }

    if (detach_from_console && daemon_child == -1)
        roken_detach_prep(argc, argv, "--daemon-child");
    rk_pidfile(NULL);

    ret = krb5_init_context(&context);
    if (ret)
        errx(1, "krb5_init_context failed: %d", ret);

    setup_signal();

    if (config_file == NULL) {
	aret = asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context));
	if (aret == -1 || config_file == NULL)
	    errx(1, "out of memory");
    }

    ret = krb5_prepend_config_files_default(config_file, &files);
    if (ret)
	krb5_err(context, 1, ret, "getting configuration files");

    ret = krb5_set_config_files(context, files);
    krb5_free_config_files(files);
    if (ret)
	krb5_err(context, 1, ret, "reading configuration files");

    init_stats_names(context);

    time_before_gone = parse_time (slave_time_gone,  "s");
    if (time_before_gone < 0)
	krb5_errx (context, 1, "couldn't parse time: %s", slave_time_gone);
    time_before_missing = parse_time (slave_time_missing,  "s");
    if (time_before_missing < 0)
	krb5_errx (context, 1, "couldn't parse time: %s", slave_time_missing);

    krb5_openlog(context, "ipropd-master", &log_facility);
    krb5_set_warn_dest(context, log_facility);

    ret = krb5_kt_register(context, &hdb_get_kt_ops);
    if(ret)
	krb5_err(context, 1, ret, "krb5_kt_register");

    ret = krb5_kt_resolve(context, keytab_str, &keytab);
    if(ret)
	krb5_err(context, 1, ret, "krb5_kt_resolve: %s", keytab_str);

    memset(&conf, 0, sizeof(conf));
    if(realm) {
	conf.mask |= KADM5_CONFIG_REALM;
	conf.realm = realm;
    }
    ret = kadm5_init_with_skey_ctx (context,
				    KADM5_ADMIN_SERVICE,
				    NULL,
				    KADM5_ADMIN_SERVICE,
				    &conf, 0, 0,
				    &kadm_handle);
    if (ret)
	krb5_err (context, 1, ret, "kadm5_init_with_password_ctx");

    server_context = (kadm5_server_context *)kadm_handle;

    log_fd = open (server_context->log_context.log_file, O_RDONLY, 0);
    if (log_fd < 0)
	krb5_err (context, 1, errno, "open %s",
		  server_context->log_context.log_file);

    if (fstat(log_fd, &st) == -1)
        krb5_err(context, 1, errno, "stat %s",
                 server_context->log_context.log_file);

    if (flock(log_fd, LOCK_SH) == -1)
        krb5_err(context, 1, errno, "shared flock %s",
                 server_context->log_context.log_file);
    kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST,
                             &current_version, &current_tstamp);
    flock(log_fd, LOCK_UN);

    signal_fd = make_signal_socket (context);
    listen_fd = make_listen_socket (context, port_str);

    krb5_warnx(context, "ipropd-master started at version: %lu",
	       (unsigned long)current_version);

    roken_detach_finish(NULL, daemon_child);
    restarter_fd = restarter(context, NULL);

    while (exit_flag == 0){
	slave *p;
	fd_set readset;
	int max_fd = 0;
	struct timeval to = {30, 0};
	uint32_t vers;
        struct stat st2;;

#ifndef NO_LIMIT_FD_SETSIZE
	if (signal_fd >= FD_SETSIZE || listen_fd >= FD_SETSIZE ||
            restarter_fd >= FD_SETSIZE)
	    krb5_errx (context, IPROPD_RESTART, "fd too large");
#endif

	FD_ZERO(&readset);
	FD_SET(signal_fd, &readset);
	max_fd = max(max_fd, signal_fd);
	FD_SET(listen_fd, &readset);
	max_fd = max(max_fd, listen_fd);
        if (restarter_fd > -1) {
            FD_SET(restarter_fd, &readset);
            max_fd = max(max_fd, restarter_fd);
        }

	for (p = slaves; p != NULL; p = p->next) {
	    if (p->flags & SLAVE_F_DEAD)
		continue;
	    FD_SET(p->fd, &readset);
	    max_fd = max(max_fd, p->fd);
	}

	ret = select (max_fd + 1,
		      &readset, NULL, NULL, &to);
	if (ret < 0) {
	    if (errno == EINTR)
		continue;
	    else
		krb5_err (context, IPROPD_RESTART, errno, "select");
	}

        if (stat(server_context->log_context.log_file, &st2) == -1) {
            krb5_warn(context, errno, "could not stat log file by path");
            st2 = st;
        }

        if (st2.st_dev != st.st_dev || st2.st_ino != st.st_ino) {
            (void) close(log_fd);

            log_fd = open(server_context->log_context.log_file, O_RDONLY, 0);
            if (log_fd < 0)
                krb5_err(context, 1, IPROPD_RESTART_SLOW, "open %s",
                          server_context->log_context.log_file);

            if (fstat(log_fd, &st) == -1)
                krb5_err(context, IPROPD_RESTART_SLOW, errno, "stat %s",
                         server_context->log_context.log_file);

            if (flock(log_fd, LOCK_SH) == -1)
                krb5_err(context, IPROPD_RESTART, errno, "shared flock %s",
                         server_context->log_context.log_file);
            kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST,
                                     &current_version, &current_tstamp);
            flock(log_fd, LOCK_UN);
        }

	if (ret == 0) {
            /* Recover from failed transactions */
            if (kadm5_log_init_nb(server_context) == 0)
                kadm5_log_end(server_context);

	    if (flock(log_fd, LOCK_SH) == -1)
                krb5_err(context, IPROPD_RESTART, errno,
                         "could not lock log file");
	    kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST,
                                     &current_version, &current_tstamp);
	    flock(log_fd, LOCK_UN);

	    if (current_version > old_version) {
		krb5_warnx(context,
			   "Missed a signal, updating slaves %lu to %lu",
			   (unsigned long)old_version,
			   (unsigned long)current_version);
		for (p = slaves; p != NULL; p = p->next) {
		    if (p->flags & SLAVE_F_DEAD)
			continue;
		    send_diffs (server_context, p, log_fd, database,
                                current_version, current_tstamp);
		}
                old_version = current_version;
	    }
	}

        if (ret && FD_ISSET(restarter_fd, &readset)) {
            exit_flag = SIGTERM;
            break;
        }

	if (ret && FD_ISSET(signal_fd, &readset)) {
#ifndef NO_UNIX_SOCKETS
	    struct sockaddr_un peer_addr;
#else
	    struct sockaddr_storage peer_addr;
#endif
	    socklen_t peer_len = sizeof(peer_addr);

	    if(recvfrom(signal_fd, (void *)&vers, sizeof(vers), 0,
			(struct sockaddr *)&peer_addr, &peer_len) < 0) {
		krb5_warn (context, errno, "recvfrom");
		continue;
	    }
	    --ret;
	    assert(ret >= 0);
	    old_version = current_version;
	    if (flock(log_fd, LOCK_SH) == -1)
                krb5_err(context, IPROPD_RESTART, errno, "shared flock %s",
                         server_context->log_context.log_file);
	    kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST,
                                     &current_version, &current_tstamp);
	    flock(log_fd, LOCK_UN);
	    if (current_version != old_version) {
                /*
                 * If current_version < old_version then the log got
                 * truncated and we'll end up doing full propagations.
                 *
                 * Truncating the log when the current version is
                 * numerically small can lead to race conditions.
                 * Ideally we should identify log versions as
                 * {init_or_trunc_time, vno}, then we could not have any
                 * such race conditions, but this would either require
                 * breaking backwards compatibility for the protocol or
                 * adding new messages to it.
                 */
		krb5_warnx(context,
			   "Got a signal, updating slaves %lu to %lu",
			   (unsigned long)old_version,
			   (unsigned long)current_version);
		for (p = slaves; p != NULL; p = p->next) {
		    if (p->flags & SLAVE_F_DEAD)
			continue;
		    send_diffs (server_context, p, log_fd, database,
                                current_version, current_tstamp);
		}
	    } else {
		krb5_warnx(context,
			   "Got a signal, but no update in log version %lu",
			   (unsigned long)current_version);
	    }
        }

	for(p = slaves; p != NULL; p = p->next) {
	    if (p->flags & SLAVE_F_DEAD)
	        continue;
	    if (ret && FD_ISSET(p->fd, &readset)) {
		--ret;
		assert(ret >= 0);
		if(process_msg (server_context, p, log_fd, database,
				current_version, current_tstamp))
		    slave_dead(context, p);
	    } else if (slave_gone_p (p))
		slave_dead(context, p);
	    else if (slave_missing_p (p))
		send_are_you_there (context, p);
	}

	if (ret && FD_ISSET(listen_fd, &readset)) {
	    add_slave (context, keytab, &slaves, listen_fd);
	    --ret;
	    assert(ret >= 0);
	}
	write_stats(context, slaves, current_version);
    }

    if(exit_flag == SIGINT || exit_flag == SIGTERM)
	krb5_warnx(context, "%s terminated", getprogname());
#ifdef SIGXCPU
    else if(exit_flag == SIGXCPU)
	krb5_warnx(context, "%s CPU time limit exceeded", getprogname());
#endif
    else
	krb5_warnx(context, "%s unexpected exit reason: %ld",
		   getprogname(), (long)exit_flag);

    write_master_down(context);

    return 0;
}
コード例 #7
0
ファイル: rlm_krb5.c プロジェクト: rssh/freeradius-server
static int verify_krb5_tgt(krb5_context context, rlm_krb5_t *inst,
			   const char *user, krb5_ccache ccache)
{
	int rcode;
	int ret;
	char phost[BUFSIZ];
	krb5_principal princ;
	krb5_keyblock *keyblock = 0;
	krb5_data packet, *server;
	krb5_auth_context auth_context = NULL;
	krb5_keytab keytab;

	char service[SERVICE_NAME_LEN] = "host";
	char *server_name = NULL;
	char *keytab_name;
	
	/* krb5_kt_read_service_key lacks const qualifier */
	memcpy(&keytab_name, &inst->keytab, sizeof(keytab_name));

	if (inst->service_princ != NULL) {
		server_name = strchr(inst->service_princ, '/');
		if (server_name != NULL) {
			*server_name = '\0';
		}

		strlcpy(service, inst->service_princ, sizeof(service));

		if (server_name != NULL) {
			*server_name = '/';
			server_name++;
		}
	}

	memset(&packet, 0, sizeof packet);
	ret = krb5_sname_to_principal(context, server_name, service,
				      KRB5_NT_SRV_HST, &princ);
	if (ret) {
		radlog(L_DBG, "rlm_krb5: [%s] krb5_sname_to_principal failed: %s",
			user, error_message(ret));

		return RLM_MODULE_REJECT;
	}

	server = krb5_princ_component(c, princ, 1);
	if (!server) {
		radlog(L_DBG, "rlm_krb5: [%s] krb5_princ_component failed.",
		       user);

		return RLM_MODULE_REJECT;
	}
	
	strlcpy(phost, server->data, sizeof(phost));

	/*
	 *  Do we have host/<host> keys?
	 *  (use default/configured keytab, kvno IGNORE_VNO to get the
	 *  first match, and enctype is currently ignored anyhow.)
	 */
	ret = krb5_kt_read_service_key(context, keytab_name, princ, 0,
				       ENCTYPE_DES_CBC_MD5, &keyblock);
	if (ret) {
		/* Keytab or service key does not exist */
		radlog(L_DBG, "rlm_krb5: verify_krb_v5_tgt: host key not found : %s",
		       error_message(ret));
		       
		return RLM_MODULE_OK;
	}
	
	if (keyblock)
		krb5_free_keyblock(context, keyblock);

	/*
	 *  Talk to the kdc and construct the ticket.
	 */
	ret = krb5_build_auth_context(inst, context, &auth_context);
	if (ret) {
		radlog(L_DBG, "rlm_krb5: [%s] krb5_build_auth_context() failed: %s",
		       user, error_message(ret));
		       
		rcode = RLM_MODULE_REJECT;
		goto cleanup;
	}
	
	ret = krb5_mk_req(context, &auth_context, 0, service, phost, NULL,
			  ccache, &packet);
	if (auth_context) {
		krb5_auth_con_free(context, auth_context);
		auth_context = NULL; /* setup for rd_req */
	}

	if (ret) {
		radlog(L_DBG, "rlm_krb5: [%s] krb5_mk_req() failed: %s",
		       user, error_message(ret));

		rcode = RLM_MODULE_REJECT;
		goto cleanup;
	}

	if (keytab_name != NULL) {
		ret = krb5_kt_resolve(context, keytab_name, &keytab);
	}

	if (keytab_name == NULL || ret) {
		ret = krb5_kt_default(context, &keytab);
	}

	/* Hmm?  The keytab was just fine a second ago! */
	if (ret) {
		radlog(L_AUTH, "rlm_krb5: [%s] krb5_kt_resolve failed: %s",
			user, error_message(ret));
			
		rcode = RLM_MODULE_REJECT;
		goto cleanup;
	}

	/* Try to use the ticket. */
	ret = krb5_build_auth_context(inst, context, &auth_context);
	if (ret) {
		radlog(L_DBG, "rlm_krb5: [%s] krb5_build_auth_context() failed: %s",
		       user, error_message(ret));

		rcode = RLM_MODULE_REJECT;
		goto cleanup;
	}
	
	ret = krb5_rd_req(context, &auth_context, &packet, princ,
			  keytab, NULL, NULL);
	if (auth_context)
		krb5_auth_con_free(context, auth_context);

	krb5_kt_close(context, keytab);

	if (ret) {
		radlog(L_AUTH, "rlm_krb5: [%s] krb5_rd_req() failed: %s",
		       user, error_message(ret));

		rcode = RLM_MODULE_REJECT;
	} else {
		rcode = RLM_MODULE_OK;
	}
	
cleanup:
	if (packet.data) {
		krb5_free_data_contents(context, &packet);
	}
	
	return rcode;
}
コード例 #8
0
ファイル: ldap_child.c プロジェクト: scaria/sssd
static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
                                               const char *realm_str,
                                               const char *princ_str,
                                               const char *keytab_name,
                                               const krb5_deltat lifetime,
                                               const char **ccname_out,
                                               time_t *expire_time_out)
{
    char *ccname;
    char *realm_name = NULL;
    char *full_princ = NULL;
    char *default_realm = NULL;
    krb5_context context = NULL;
    krb5_keytab keytab = NULL;
    krb5_ccache ccache = NULL;
    krb5_principal kprinc;
    krb5_creds my_creds;
    krb5_get_init_creds_opt options;
    krb5_error_code krberr;
    krb5_timestamp kdc_time_offset;
    int kdc_time_offset_usec;
    int ret;

    krberr = krb5_init_context(&context);
    if (krberr) {
        DEBUG(2, ("Failed to init kerberos context\n"));
        return krberr;
    }

    if (!realm_str) {
        krberr = krb5_get_default_realm(context, &default_realm);
        if (krberr) {
            DEBUG(2, ("Failed to get default realm name: %s\n",
                      sss_krb5_get_error_message(context, krberr)));
            goto done;
        }

        realm_name = talloc_strdup(memctx, default_realm);
        krb5_free_default_realm(context, default_realm);
        if (!realm_name) {
            krberr = KRB5KRB_ERR_GENERIC;
            goto done;
        }

    } else {
        realm_name = talloc_strdup(memctx, realm_str);
        if (!realm_name) {
            krberr = KRB5KRB_ERR_GENERIC;
            goto done;
        }
    }

    if (princ_str) {
        if (!strchr(princ_str, '@')) {
            full_princ = talloc_asprintf(memctx, "%s@%s",
                                         princ_str, realm_name);
        } else {
            full_princ = talloc_strdup(memctx, princ_str);
        }
    } else {
        char hostname[512];

        ret = gethostname(hostname, 511);
        if (ret == -1) {
            krberr = KRB5KRB_ERR_GENERIC;
            goto done;
        }
        hostname[511] = '\0';

        ret = select_principal_from_keytab(memctx, hostname, realm_name,
                                           keytab_name, &full_princ, NULL, NULL);
        if (ret) goto done;
    }
    if (!full_princ) {
        krberr = KRB5KRB_ERR_GENERIC;
        goto done;
    }
    DEBUG(4, ("Principal name is: [%s]\n", full_princ));

    krberr = krb5_parse_name(context, full_princ, &kprinc);
    if (krberr) {
        DEBUG(2, ("Unable to build principal: %s\n",
                  sss_krb5_get_error_message(context, krberr)));
        goto done;
    }

    if (keytab_name) {
        krberr = krb5_kt_resolve(context, keytab_name, &keytab);
    } else {
        krberr = krb5_kt_default(context, &keytab);
    }
    if (krberr) {
        DEBUG(0, ("Failed to read keytab file: %s\n",
                  sss_krb5_get_error_message(context, krberr)));
        goto done;
    }

    /* Verify the keytab */
    ret = sss_krb5_verify_keytab_ex(full_princ, keytab_name, context, keytab);
    if (ret) {
        DEBUG(2, ("Unable to verify principal is present in the keytab\n"));
        krberr = KRB5_KT_IOERR;
        goto done;
    }

    ccname = talloc_asprintf(memctx, "FILE:%s/ccache_%s", DB_PATH, realm_name);
    if (!ccname) {
        krberr = KRB5KRB_ERR_GENERIC;
        goto done;
    }

    krberr = krb5_cc_resolve(context, ccname, &ccache);
    if (krberr) {
        DEBUG(2, ("Failed to set cache name: %s\n",
                  sss_krb5_get_error_message(context, krberr)));
        goto done;
    }

    memset(&my_creds, 0, sizeof(my_creds));
    memset(&options, 0, sizeof(options));

    krb5_get_init_creds_opt_set_address_list(&options, NULL);
    krb5_get_init_creds_opt_set_forwardable(&options, 0);
    krb5_get_init_creds_opt_set_proxiable(&options, 0);
    krb5_get_init_creds_opt_set_tkt_life(&options, lifetime);

    krberr = krb5_get_init_creds_keytab(context, &my_creds, kprinc,
                                        keytab, 0, NULL, &options);

    if (krberr) {
        DEBUG(0, ("Failed to init credentials: %s\n",
                  sss_krb5_get_error_message(context, krberr)));
        sss_log(SSS_LOG_ERR, "Failed to initialize credentials using keytab [%s]: %s. "
                             "Unable to create GSSAPI-encrypted LDAP connection.",
                             keytab_name, sss_krb5_get_error_message(context, krberr));
        goto done;
    }

    krberr = krb5_cc_initialize(context, ccache, kprinc);
    if (krberr) {
        DEBUG(2, ("Failed to init ccache: %s\n",
                  sss_krb5_get_error_message(context, krberr)));
        goto done;
    }

    krberr = krb5_cc_store_cred(context, ccache, &my_creds);
    if (krberr) {
        DEBUG(2, ("Failed to store creds: %s\n",
                  sss_krb5_get_error_message(context, krberr)));
        goto done;
    }

    krberr = krb5_get_time_offsets(context, &kdc_time_offset, &kdc_time_offset_usec);
    if (krberr) {
        DEBUG(2, ("Failed to get KDC time offset: %s\n",
                  sss_krb5_get_error_message(context, krberr)));
        kdc_time_offset = 0;
    } else {
        if (kdc_time_offset_usec > 0) {
            kdc_time_offset++;
        }
    }

    krberr = 0;
    *ccname_out = ccname;
    *expire_time_out = my_creds.times.endtime - kdc_time_offset;

done:
    if (keytab) krb5_kt_close(context, keytab);
    if (context) krb5_free_context(context);
    return krberr;
}
コード例 #9
0
ファイル: copy_ccache.c プロジェクト: 0x24bin/winexe-1
OM_uint32
_gsskrb5_krb5_import_cred(OM_uint32 *minor_status,
			  krb5_ccache id,
			  krb5_principal keytab_principal,
			  krb5_keytab keytab,
			  gss_cred_id_t *cred)
{
    krb5_context context;
    krb5_error_code kret;
    gsskrb5_cred handle;
    OM_uint32 ret;

    *cred = NULL;

    GSSAPI_KRB5_INIT (&context);

    handle = calloc(1, sizeof(*handle));
    if (handle == NULL) {
	_gsskrb5_clear_status ();
	*minor_status = ENOMEM;
        return (GSS_S_FAILURE);
    }
    HEIMDAL_MUTEX_init(&handle->cred_id_mutex);

    handle->usage = 0;

    if (id) {
	char *str;

	handle->usage |= GSS_C_INITIATE;

	kret = krb5_cc_get_principal(context, id,
				     &handle->principal);
	if (kret) {
	    free(handle);
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}
	
	if (keytab_principal) {
	    krb5_boolean match;

	    match = krb5_principal_compare(context,
					   handle->principal,
					   keytab_principal);
	    if (match == FALSE) {
		krb5_free_principal(context, handle->principal);
		free(handle);
		_gsskrb5_clear_status ();
		*minor_status = EINVAL;
		return GSS_S_FAILURE;
	    }
	}

	ret = __gsskrb5_ccache_lifetime(minor_status,
					context,
					id,
					handle->principal,
					&handle->lifetime);
	if (ret != GSS_S_COMPLETE) {
	    krb5_free_principal(context, handle->principal);
	    free(handle);
	    return ret;
	}


	kret = krb5_cc_get_full_name(context, id, &str);
	if (kret)
	    goto out;

	kret = krb5_cc_resolve(context, str, &handle->ccache);
	free(str);
	if (kret)
	    goto out;
    }


    if (keytab) {
	char *str;

	handle->usage |= GSS_C_ACCEPT;

	if (keytab_principal && handle->principal == NULL) {
	    kret = krb5_copy_principal(context,
				       keytab_principal,
				       &handle->principal);
	    if (kret)
		goto out;
	}

	kret = krb5_kt_get_full_name(context, keytab, &str);
	if (kret)
	    goto out;

	kret = krb5_kt_resolve(context, str, &handle->keytab);
	free(str);
	if (kret)
	    goto out;
    }


    if (id || keytab) {
	ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
	if (ret == GSS_S_COMPLETE)
	    ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
					 &handle->mechanisms);
	if (ret != GSS_S_COMPLETE) {
	    kret = *minor_status;
	    goto out;
	}
    }

    *minor_status = 0;
    *cred = (gss_cred_id_t)handle;
    return GSS_S_COMPLETE;

out:
    gss_release_oid_set(minor_status, &handle->mechanisms);
    if (handle->ccache)
	krb5_cc_close(context, handle->ccache);
    if (handle->keytab)
	krb5_kt_close(context, handle->keytab);
    if (handle->principal)
	krb5_free_principal(context, handle->principal);
    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
    free(handle);
    *minor_status = kret;
    return GSS_S_FAILURE;
}
コード例 #10
0
/*
 *	Validate user/pass (Heimdal)
 */
static rlm_rcode_t krb5_auth(void *instance, REQUEST *request)
{
	rlm_krb5_t *inst = instance;
	rlm_rcode_t rcode;
	
	krb5_error_code ret;
	
	krb5_principal client;
	krb5_ccache ccache;
	krb5_keytab keytab;
	krb5_verify_opt options;
	krb5_context *context = NULL;
	
	/*
	 *	See above in MIT krb5_auth
	 */
	ret = krb5_copy_context(*(inst->context), context);
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Error cloning krb5 context: %s",
		       inst->xlat_name, error_message(ret));
		
		return RLM_MODULE_FAIL;
	}
	
	/*
	 *	Setup krb5_verify_user options
	 *
	 *	Not entirely sure this is necessary, but as we use context 
	 *	to get the cache handle, we probably do have to do this with
	 *	the cloned context.
	 */
	krb5_cc_default(*context, &ccache);
	
	krb5_verify_opt_init(&options);
	krb5_verify_opt_set_ccache(&options, ccache);
	
	memset(&keytab, 0, sizeof(keytab));
	ret = inst->keytabname ? 
		krb5_kt_resolve(*context, inst->keytabname, &keytab) :
		krb5_kt_default(*context, &keytab);
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Resolving keytab failed: %s",
		       inst->xlat_name, error_message(ret));
		
		goto cleanup;
	}
	
	krb5_verify_opt_set_keytab(&options, keytab);
	krb5_verify_opt_set_secure(&options, TRUE);

	if (inst->service) {
		krb5_verify_opt_set_service(&options, inst->service);
	}
	
	rcode = krb5_parse_user(inst, request, &client);
	if (rcode != RLM_MODULE_OK) goto cleanup;

	/* 
	 *	Verify the user, using the options we set in instantiate
	 */
	ret = krb5_verify_user_opt(*context, client,
				   request->password->vp_strvalue,
				   &options);
	if (ret) {
		switch (ret) {
		case KRB5_LIBOS_BADPWDMATCH:
		case KRB5KRB_AP_ERR_BAD_INTEGRITY:
			RDEBUG("Provided password was incorrect: %s",
			       error_message(ret));
			rcode = RLM_MODULE_REJECT;
		
			break;
		case KRB5KDC_ERR_KEY_EXP:
		case KRB5KDC_ERR_CLIENT_REVOKED:
		case KRB5KDC_ERR_SERVICE_REVOKED:
			RDEBUG("Account has been locked out: %s",
			       error_message(ret));
			rcode = RLM_MODULE_USERLOCK;
		
			break;
		case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
			RDEBUG("User not found: %s", error_message(ret));
			rcode = RLM_MODULE_NOTFOUND;
					
		default:
			radlog(L_ERR, "rlm_krb5 (%s): Verifying user failed: "
			       "%s", inst->xlat_name, error_message(ret));
			rcode = RLM_MODULE_FAIL;
		
			break;
		}

		goto cleanup;
	}
	
	cleanup:
	
	krb5_free_context(*context);
	krb5_kt_close(*context, keytab);
	
	return rcode;
}
コード例 #11
0
ファイル: ad.c プロジェクト: jonrober/krb5-sync
/*
 * Given the plugin options, a Kerberos context, and a pointer to krb5_ccache
 * storage, initialize a memory cache using the configured keytab to obtain
 * initial credentials.  Returns a Kerberos status code.
 */
static krb5_error_code
get_creds(kadm5_hook_modinfo *config, krb5_context ctx, krb5_ccache *cc)
{
    krb5_error_code code;
    krb5_keytab kt = NULL;
    krb5_principal princ = NULL;
    krb5_get_init_creds_opt *opts = NULL;
    krb5_creds creds;
    bool creds_valid = false;
    const char *realm UNUSED;

    /* Initialize the credential cache pointer to NULL. */
    *cc = NULL;

    /* Ensure the configuration is sane. */
    CHECK_CONFIG(ad_keytab);
    CHECK_CONFIG(ad_principal);

    /* Resolve the keytab and principal used to get credentials. */
    code = krb5_kt_resolve(ctx, config->ad_keytab, &kt);
    if (code != 0)
        goto fail;
    code = krb5_parse_name(ctx, config->ad_principal, &princ);
    if (code != 0)
        goto fail;

    /* Set our credential acquisition options. */
    code = krb5_get_init_creds_opt_alloc(ctx, &opts);
    if (code != 0)
        goto fail;
    realm = krb5_principal_get_realm(ctx, princ);
    krb5_get_init_creds_opt_set_default_flags(ctx, "krb5-sync", realm, opts);

    /* Obtain credentials. */
    memset(&creds, 0, sizeof(creds));
    code = krb5_get_init_creds_keytab(ctx, &creds, princ, kt, 0, NULL, opts);
    if (code != 0)
        goto fail;
    krb5_get_init_creds_opt_free(ctx, opts);
    opts = NULL;
    krb5_kt_close(ctx, kt);
    kt = NULL;
    creds_valid = true;

    /* Open and initialize the credential cache. */
    code = krb5_cc_resolve(ctx, CACHE_NAME, cc);
    if (code != 0)
        goto fail;
    code = krb5_cc_initialize(ctx, *cc, princ);
    if (code == 0)
        code = krb5_cc_store_cred(ctx, *cc, &creds);
    if (code != 0) {
        krb5_cc_close(ctx, *cc);
        *cc = NULL;
        goto fail;
    }

    /* Clean up and return success. */
    krb5_free_cred_contents(ctx, &creds);
    krb5_free_principal(ctx, princ);
    return 0;

fail:
    if (kt != NULL)
        krb5_kt_close(ctx, kt);
    if (princ != NULL)
        krb5_free_principal(ctx, princ);
    if (opts != NULL)
        krb5_get_init_creds_opt_free(ctx, opts);
    if (creds_valid)
        krb5_free_cred_contents(ctx, &creds);
    return code;
}
コード例 #12
0
/* 
 *  Validate userid/passwd (MIT)
 */
static rlm_rcode_t krb5_auth(void *instance, REQUEST *request)
{
	rlm_krb5_t *inst = instance;
	rlm_rcode_t rcode;	
	krb5_error_code ret;

	krb5_principal client;
	krb5_creds init_creds;
	krb5_keytab keytab;
	krb5_context *context = NULL;
	
	/*
	 *	All the snippets on threadsafety say that individual threads
	 *	must each use their own copy of context.
	 *
	 *	As we don't have any per thread instantiation, we either have
	 *	to clone inst->context on every request, or use the connection
	 *	API.
	 *
	 *	@todo Use the connection API (3.0 only).
	 */
	ret = krb5_copy_context(*(inst->context), context);
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Error cloning krb5 context: %s",
		       inst->xlat_name, error_message(ret));
		
		return RLM_MODULE_FAIL;
	}

	/*
	 *	Check we have all the required VPs, and convert the username
	 *	into a principal.
	 */
	rcode = krb5_parse_user(inst, request, &client);
	if (rcode != RLM_MODULE_OK) goto cleanup;

	/*
	 * 	Retrieve the TGT from the TGS/KDC and check we can decrypt it.
	 */
	memset(&init_creds, 0, sizeof(init_creds));
	ret = krb5_get_init_creds_password(*context, &init_creds, client,
					   request->password->vp_strvalue,
					   NULL, NULL, 0, NULL,
					   inst->gic_options);
	if (ret) {
		error:
		switch (ret) {
		case KRB5_LIBOS_BADPWDMATCH:
		case KRB5KRB_AP_ERR_BAD_INTEGRITY:
			RDEBUG("Provided password was incorrect: %s",
			       error_message(ret));
			rcode = RLM_MODULE_REJECT;
		
			break;
			
		case KRB5KDC_ERR_KEY_EXP:
		case KRB5KDC_ERR_CLIENT_REVOKED:
		case KRB5KDC_ERR_SERVICE_REVOKED:
			RDEBUG("Account has been locked out: %s",
			       error_message(ret));
			rcode = RLM_MODULE_USERLOCK;
		
			break;
			
		case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
			RDEBUG("User not found: %s", error_message(ret));
			rcode = RLM_MODULE_NOTFOUND;
			
		default:
			radlog(L_ERR, "rlm_krb5 (%s): Failed getting/verifying "
			       "credentials: %s", inst->xlat_name,
			       error_message(ret));
			rcode = RLM_MODULE_FAIL;
		
			break;
		}

		goto cleanup;
	}
	
	RDEBUG("Successfully retrieved and decrypted TGT");
	
	memset(&keytab, 0, sizeof(keytab));
	ret = inst->keytabname ? 
		krb5_kt_resolve(*context, inst->keytabname, &keytab) :
		krb5_kt_default(*context, &keytab);
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Resolving keytab failed: %s",
		       inst->xlat_name, error_message(ret));
		
		goto cleanup;
	}
	
	ret = krb5_verify_init_creds(*context, &init_creds, inst->server,
				     keytab, NULL, inst->vic_options);
	if (ret) goto error;
 
	cleanup:

	krb5_free_cred_contents(*context, &init_creds);
	krb5_free_context(*context);
	krb5_kt_close(*context, keytab);
	
	return rcode;
}
コード例 #13
0
ファイル: config.c プロジェクト: Kendra123/heimdal
static krb5_error_code
ccache_init_system(void)
{
    kcm_ccache ccache;
    krb5_error_code ret;

    if (system_cache_name == NULL)
	system_cache_name = kcm_system_config_get_string("cc_name");

    ret = kcm_ccache_new(kcm_context,
			 system_cache_name ? system_cache_name : "SYSTEM",
			 &ccache);
    if (ret)
	return ret;

    ccache->flags |= KCM_FLAGS_OWNER_IS_SYSTEM;
    ccache->flags |= KCM_FLAGS_USE_KEYTAB;

    ret = parse_owners(ccache);
    if (ret)
	return ret;

    ret = krb5_parse_name(kcm_context, system_principal, &ccache->client);
    if (ret) {
	kcm_release_ccache(kcm_context, ccache);
	return ret;
    }

    if (system_server == NULL)
	system_server = kcm_system_config_get_string("server");

    if (system_server != NULL) {
	ret = krb5_parse_name(kcm_context, system_server, &ccache->server);
	if (ret) {
	    kcm_release_ccache(kcm_context, ccache);
	    return ret;
	}
    }

    if (system_keytab == NULL)
	system_keytab = kcm_system_config_get_string("keytab_name");

    if (system_keytab != NULL) {
	ret = krb5_kt_resolve(kcm_context, system_keytab, &ccache->key.keytab);
    } else {
	ret = krb5_kt_default(kcm_context, &ccache->key.keytab);
    }
    if (ret) {
	kcm_release_ccache(kcm_context, ccache);
	return ret;
    }

    if (renew_life == NULL)
	renew_life = kcm_system_config_get_string("renew_life");

    if (renew_life == NULL)
	renew_life = "1 month";

    if (renew_life != NULL) {
	ccache->renew_life = parse_time(renew_life, "s");
	if (ccache->renew_life < 0) {
	    kcm_release_ccache(kcm_context, ccache);
	    return EINVAL;
	}
    }

    if (ticket_life == NULL)
	ticket_life = kcm_system_config_get_string("ticket_life");

    if (ticket_life != NULL) {
	ccache->tkt_life = parse_time(ticket_life, "s");
	if (ccache->tkt_life < 0) {
	    kcm_release_ccache(kcm_context, ccache);
	    return EINVAL;
	}
    }

    if (system_perms == NULL)
	system_perms = kcm_system_config_get_string("mode");

    if (system_perms != NULL) {
	int mode;

	if (sscanf(system_perms, "%o", &mode) != 1)
	    return EINVAL;

	ccache->mode = mode;
    }

    if (disallow_getting_krbtgt == -1) {
	disallow_getting_krbtgt =
	    krb5_config_get_bool_default(kcm_context, NULL, FALSE, "kcm",
					 "disallow-getting-krbtgt", NULL);
    }

    /* enqueue default actions for credentials cache */
    ret = kcm_ccache_enqueue_default(kcm_context, ccache, NULL);

    kcm_release_ccache(kcm_context, ccache); /* retained by event queue */

    return ret;
}
コード例 #14
0
ファイル: ap-req.c プロジェクト: asdlei00/freebsd
int
main(int argc, char **argv)
{
    krb5_context context;
    krb5_error_code ret;
    int optidx = 0;
    const char *principal, *keytab, *ccache;
    krb5_ccache id;
    krb5_keytab kt;
    krb5_principal sprincipal;

    setprogname(argv[0]);

    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
        usage(1);

    if (help_flag)
        usage (0);

    if(version_flag) {
        print_version(NULL);
        exit(0);
    }

    argc -= optidx;
    argv += optidx;

    if (argc < 3)
        usage(1);

    principal = argv[0];
    keytab = argv[1];
    ccache = argv[2];

    ret = krb5_init_context(&context);
    if (ret)
        errx (1, "krb5_init_context failed: %d", ret);

    ret = krb5_cc_resolve(context, ccache, &id);
    if (ret)
        krb5_err(context, 1, ret, "krb5_cc_resolve");

    ret = krb5_parse_name(context, principal, &sprincipal);
    if (ret)
        krb5_err(context, 1, ret, "krb5_parse_name");

    ret = krb5_kt_resolve(context, keytab, &kt);
    if (ret)
        krb5_err(context, 1, ret, "krb5_kt_resolve");

    test_ap(context, sprincipal, kt, id, 0);
    test_ap(context, sprincipal, kt, id, AP_OPTS_MUTUAL_REQUIRED);

    krb5_cc_close(context, id);
    krb5_kt_close(context, kt);
    krb5_free_principal(context, sprincipal);

    krb5_free_context(context);

    return ret;
}
コード例 #15
0
ファイル: kssl.c プロジェクト: awakecoding/libressl
/*	Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"),
**		and krb5 AP_REQ message & message length,
**	Return Kerberos session key and client principle
**		to SSL Server in KSSL_CTX *kssl_ctx.
**
**	19990702	VRS 	Started.
*/
krb5_error_code
kssl_sget_tkt(
	/* UPDATE */	KSSL_CTX		*kssl_ctx,
	/* IN     */	krb5_data		*indata,
	/* OUT    */	krb5_ticket_times	*ttimes,
	/* OUT    */	KSSL_ERR		*kssl_err  )
{
	krb5_error_code			krb5rc = KRB5KRB_ERR_GENERIC;
	static krb5_context		krb5context = NULL;
	static krb5_auth_context	krb5auth_context = NULL;
	krb5_ticket 			*krb5ticket = NULL;
	KRB5_TKTBODY 			*asn1ticket = NULL;
	const unsigned char		*p;
	krb5_keytab 			krb5keytab = NULL;
	krb5_keytab_entry		kt_entry;
	krb5_principal			krb5server;
	krb5_rcache                     rcache = NULL;

	kssl_err_set(kssl_err, 0, "");

	if (!kssl_ctx) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
		    "No kssl_ctx defined.\n");
		goto err;
	}

#ifdef KSSL_DEBUG
	printf("in kssl_sget_tkt(%s)\n", kstring(kssl_ctx->service_name));
#endif	/* KSSL_DEBUG */

	if (!krb5context && (krb5rc = krb5_init_context(&krb5context))) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
		    "krb5_init_context() fails.\n");
		goto err;
	}
	if (krb5auth_context &&
	    (krb5rc = krb5_auth_con_free(krb5context, krb5auth_context))) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
		    "krb5_auth_con_free() fails.\n");
		goto err;
	} else
		krb5auth_context = NULL;
	if (!krb5auth_context &&
	    (krb5rc = krb5_auth_con_init(krb5context, &krb5auth_context))) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
		    "krb5_auth_con_init() fails.\n");
		goto err;
	}

	if ((krb5rc = krb5_auth_con_getrcache(krb5context, krb5auth_context,
	    &rcache))) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
		    "krb5_auth_con_getrcache() fails.\n");
		goto err;
	}

	if ((krb5rc = krb5_sname_to_principal(krb5context, NULL,
	    (kssl_ctx->service_name) ? kssl_ctx->service_name : KRB5SVC,
	    KRB5_NT_SRV_HST, &krb5server)) != 0) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
		    "krb5_sname_to_principal() fails.\n");
		goto err;
	}

	if (rcache == NULL) {
		if ((krb5rc = krb5_get_server_rcache(krb5context,
		    krb5_princ_component(krb5context, krb5server, 0),
		    &rcache))) {
			kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
			    "krb5_get_server_rcache() fails.\n");
			goto err;
		}
	}

	if ((krb5rc = krb5_auth_con_setrcache(krb5context, krb5auth_context,
	    rcache))) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
		    "krb5_auth_con_setrcache() fails.\n");
		goto err;
	}


	/*	kssl_ctx->keytab_file == NULL ==> use Kerberos default
	*/
	if (kssl_ctx->keytab_file) {
		krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file,
		    &krb5keytab);
		if (krb5rc) {
			kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
			    "krb5_kt_resolve() fails.\n");
			goto err;
		}
	} else {
		krb5rc = krb5_kt_default(krb5context, &krb5keytab);
		if (krb5rc) {
			kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
			    "krb5_kt_default() fails.\n");
			goto err;
		}
	}

	/*	Actual Kerberos5 krb5_recvauth() has initial conversation here
	**	o	check KRB5_SENDAUTH_BADAUTHVERS
	**		unless KRB5_RECVAUTH_SKIP_VERSION
	**	o	check KRB5_SENDAUTH_BADAPPLVERS
	**	o	send "0" msg if all OK
	*/

	/*  20010411 was using AP_REQ instead of true KerberosWrapper
	**
	**  if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context,
	**			&krb5in_data, krb5server, krb5keytab,
	**			&ap_option, &krb5ticket)) != 0)  { Error }
	*/

	p = (unsigned char *)indata->data;
	if ((asn1ticket = (KRB5_TKTBODY *) d2i_KRB5_TICKET(NULL, &p,
	    (long)indata->length)) == NULL) {
		(void) snprintf(kssl_err->text, KSSL_ERR_MAX,
		    "d2i_KRB5_TICKET() ASN.1 decode failure.\n");
		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
		goto err;
	}

	/* Was:  krb5rc = krb5_decode_ticket(krb5in_data,&krb5ticket)) != 0) */
	if ((krb5rc = kssl_TKT2tkt(krb5context, asn1ticket, &krb5ticket,
	    kssl_err)) != 0) {
		(void) snprintf(kssl_err->text, KSSL_ERR_MAX,
		    "Error converting ASN.1 ticket to krb5_ticket.\n");
		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
		goto err;
	}

	if (!krb5_principal_compare(krb5context, krb5server,
	    krb5ticket->server))  {
		krb5rc = KRB5_PRINC_NOMATCH;
		(void) snprintf(kssl_err->text, KSSL_ERR_MAX,
		    "server principal != ticket principal\n");
		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
		goto err;
	}
	if ((krb5rc = krb5_kt_get_entry(krb5context, krb5keytab,
	    krb5ticket->server, krb5ticket->enc_part.kvno,
	    krb5ticket->enc_part.enctype, &kt_entry)) != 0)  {
		(void) snprintf(kssl_err->text, KSSL_ERR_MAX,
		    "krb5_kt_get_entry() fails with %x.\n", krb5rc);
		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
		goto err;
	}
	if ((krb5rc = krb5_decrypt_tkt_part(krb5context, &kt_entry.key,
	    krb5ticket)) != 0)  {
		(void) snprintf(kssl_err->text, KSSL_ERR_MAX,
		    "krb5_decrypt_tkt_part() failed.\n");
		kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
		goto err;
	} else {
		krb5_kt_free_entry(krb5context, &kt_entry);
#ifdef KSSL_DEBUG
		{
			int i;
			krb5_address **paddr = krb5ticket->enc_part2->caddrs;
			printf("Decrypted ticket fields:\n");
			printf("\tflags: %X, transit-type: %X",
			    krb5ticket->enc_part2->flags,
			    krb5ticket->enc_part2->transited.tr_type);
			print_krb5_data("\ttransit-data: ",
			    &(krb5ticket->enc_part2->transited.tr_contents));
			printf("\tcaddrs: %p, authdata: %p\n",
			    krb5ticket->enc_part2->caddrs,
			    krb5ticket->enc_part2->authorization_data);
			if (paddr) {
				printf("\tcaddrs:\n");
				for (i = 0; paddr[i] != NULL; i++) {
					krb5_data d;
					d.length = paddr[i]->length;
					d.data = paddr[i]->contents;
					print_krb5_data("\t\tIP: ", &d);
				}
			}
			printf("\tstart/auth/end times: %d / %d / %d\n",
			    krb5ticket->enc_part2->times.starttime,
			    krb5ticket->enc_part2->times.authtime,
			    krb5ticket->enc_part2->times.endtime);
		}
#endif	/* KSSL_DEBUG */
	}

	krb5rc = KRB5_NO_TKT_SUPPLIED;
	if (!krb5ticket || !krb5ticket->enc_part2 ||
	    !krb5ticket->enc_part2->client ||
	    !krb5ticket->enc_part2->client->data ||
	    !krb5ticket->enc_part2->session) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
		    "bad ticket from krb5_rd_req.\n");
	} else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT,
	    &krb5ticket->enc_part2->client->realm,
	    krb5ticket->enc_part2->client->data,
	    krb5ticket->enc_part2->client->length)) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
		    "kssl_ctx_setprinc() fails.\n");
	} else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session)) {
		kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
		    "kssl_ctx_setkey() fails.\n");
	} else if (krb5ticket->enc_part2->flags & TKT_FLG_INVALID) {
		krb5rc = KRB5KRB_AP_ERR_TKT_INVALID;
		kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
		    "invalid ticket from krb5_rd_req.\n");
	} else
		krb5rc = 0;

	kssl_ctx->enctype = krb5ticket->enc_part.enctype;
	ttimes->authtime = krb5ticket->enc_part2->times.authtime;
	ttimes->starttime = krb5ticket->enc_part2->times.starttime;
	ttimes->endtime = krb5ticket->enc_part2->times.endtime;
	ttimes->renew_till = krb5ticket->enc_part2->times.renew_till;

err:
#ifdef KSSL_DEBUG
	kssl_ctx_show(kssl_ctx);
#endif	/* KSSL_DEBUG */

	if (asn1ticket)
		KRB5_TICKET_free((KRB5_TICKET *) asn1ticket);
	if (krb5keytab)
		krb5_kt_close(krb5context, krb5keytab);
	if (krb5ticket)
		krb5_free_ticket(krb5context, krb5ticket);
	if (krb5server)
		krb5_free_principal(krb5context, krb5server);
	return (krb5rc);
}
コード例 #16
0
ファイル: keytab.c プロジェクト: Marvin-Lee/libwmiclient
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_default(krb5_context context, krb5_keytab *id)
{
    return krb5_kt_resolve (context, context->default_keytab, id);
}
コード例 #17
0
ファイル: srv_keytab.c プロジェクト: hef/samba
krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
                                       krb5_context context,
                                       const char *keytab_name,
                                       const char *samAccountName,
                                       const char *realm,
                                       const char **SPNs,
                                       int num_SPNs,
                                       const char *saltPrincipal,
                                       const char *new_secret,
                                       const char *old_secret,
                                       int kvno,
                                       uint32_t supp_enctypes,
                                       bool delete_all_kvno,
                                       krb5_keytab *_keytab,
                                       const char **error_string)
{
    krb5_keytab keytab;
    krb5_error_code ret;
    bool found_previous;
    TALLOC_CTX *tmp_ctx;
    krb5_principal *principals = NULL;

    if (keytab_name == NULL) {
        return ENOENT;
    }

    ret = krb5_kt_resolve(context, keytab_name, &keytab);
    if (ret) {
        *error_string = smb_get_krb5_error_message(context,
                        ret, parent_ctx);
        return ret;
    }

    DEBUG(5, ("Opened keytab %s\n", keytab_name));

    tmp_ctx = talloc_new(parent_ctx);
    if (!tmp_ctx) {
        return ENOMEM;
    }

    /* Get the principal we will store the new keytab entries under */
    ret = principals_from_list(tmp_ctx,
                               samAccountName, realm, SPNs, num_SPNs,
                               context, &principals, error_string);

    if (ret != 0) {
        *error_string = talloc_asprintf(parent_ctx,
                                        "Failed to load principals from ldb message: %s\n",
                                        *error_string);
        goto done;
    }

    ret = remove_old_entries(tmp_ctx, kvno, principals, delete_all_kvno,
                             context, keytab, &found_previous, error_string);
    if (ret != 0) {
        *error_string = talloc_asprintf(parent_ctx,
                                        "Failed to remove old principals from keytab: %s\n",
                                        *error_string);
        goto done;
    }

    if (!delete_all_kvno) {
        /* Create a new keytab.  If during the cleanout we found
         * entires for kvno -1, then don't try and duplicate them.
         * Otherwise, add kvno, and kvno -1 */

        ret = create_keytab(tmp_ctx,
                            samAccountName, realm, saltPrincipal,
                            kvno, new_secret, old_secret,
                            supp_enctypes, principals,
                            context, keytab,
                            found_previous ? false : true,
                            error_string);
        if (ret) {
            talloc_steal(parent_ctx, *error_string);
        }
    }

    if (ret == 0 && _keytab != NULL) {
        /* caller wants the keytab handle back */
        *_keytab = keytab;
    }

done:
    keytab_principals_free(context, principals);
    if (ret != 0 || _keytab == NULL) {
        krb5_kt_close(context, keytab);
    }
    talloc_free(tmp_ctx);
    return ret;
}
コード例 #18
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_auth_context ac = NULL;
    krb5_principal c1, c2;
    krb5_authenticator authent;
    krb5_keytab keytab;
    krb5_socket_t sock = rk_INVALID_SOCKET;
    HDB *db = NULL;
    int optidx = 0;
    char *tmp_db;
    krb5_log_facility *fac;
    int nprincs;

    setprogname(argv[0]);

    ret = krb5_init_context(&context);
    if(ret)
	exit(1);

    ret = krb5_openlog(context, "hpropd", &fac);
    if(ret)
	errx(1, "krb5_openlog");
    krb5_set_warn_dest(context, fac);

    if(getarg(args, num_args, argc, argv, &optidx))
	usage(1);

    if(local_realm != NULL)
	krb5_set_default_realm(context, local_realm);

    if(help_flag)
	usage(0);
    if(version_flag) {
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    if (argc != 0)
	usage(1);

    if (database == NULL)
	database = hdb_default_db(context);

    if(from_stdin) {
	sock = STDIN_FILENO;
    } else {
	struct sockaddr_storage ss;
	struct sockaddr *sa = (struct sockaddr *)&ss;
	socklen_t sin_len = sizeof(ss);
	char addr_name[256];
	krb5_ticket *ticket;
	char *server;

	sock = STDIN_FILENO;
#ifdef SUPPORT_INETD
	if (inetd_flag == -1) {
	    if (getpeername (sock, sa, &sin_len) < 0) {
		inetd_flag = 0;
	    } else {
		inetd_flag = 1;
	    }
	}
#else
	inetd_flag = 0;
#endif
	if (!inetd_flag) {
	    mini_inetd (krb5_getportbyname (context, "hprop", "tcp",
					    HPROP_PORT), &sock);
	}
	sin_len = sizeof(ss);
	if(getpeername(sock, sa, &sin_len) < 0)
	    krb5_err(context, 1, errno, "getpeername");

	if (inet_ntop(sa->sa_family,
		      socket_get_address (sa),
		      addr_name,
		      sizeof(addr_name)) == NULL)
	    strlcpy (addr_name, "unknown address",
		     sizeof(addr_name));

	krb5_log(context, fac, 0, "Connection from %s", addr_name);

	ret = krb5_kt_register(context, &hdb_kt_ops);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_kt_register");

	if (ktname != NULL) {
	    ret = krb5_kt_resolve(context, ktname, &keytab);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_kt_resolve %s", ktname);
	} else {
	    ret = krb5_kt_default (context, &keytab);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_kt_default");
	}

	ret = krb5_recvauth(context, &ac, &sock, HPROP_VERSION, NULL,
			    0, keytab, &ticket);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_recvauth");
	
	ret = krb5_unparse_name(context, ticket->server, &server);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_unparse_name");
	if (strncmp(server, "hprop/", 5) != 0)
	    krb5_errx(context, 1, "ticket not for hprop (%s)", server);

	free(server);
	krb5_free_ticket (context, ticket);

	ret = krb5_auth_con_getauthenticator(context, ac, &authent);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_auth_con_getauthenticator");

	ret = krb5_make_principal(context, &c1, NULL, "kadmin", "hprop", NULL);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_make_principal");
	_krb5_principalname2krb5_principal(context, &c2,
					   authent->cname, authent->crealm);
	if(!krb5_principal_compare(context, c1, c2)) {
	    char *s;
	    ret = krb5_unparse_name(context, c2, &s);
	    if (ret)
		s = "unparseable name";
	    krb5_errx(context, 1, "Unauthorized connection from %s", s);
	}
	krb5_free_principal(context, c1);
	krb5_free_principal(context, c2);

	ret = krb5_kt_close(context, keytab);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_kt_close");
    }

    if(!print_dump) {
	asprintf(&tmp_db, "%s~", database);

	ret = hdb_create(context, &db, tmp_db);
	if(ret)
	    krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db);
	ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600);
	if(ret)
	    krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db);
    }

    nprincs = 0;
    while(1){
	krb5_data data;
	hdb_entry_ex entry;

	if(from_stdin) {
	    ret = krb5_read_message(context, &sock, &data);
	    if(ret != 0 && ret != HEIM_ERR_EOF)
		krb5_err(context, 1, ret, "krb5_read_message");
	} else {
	    ret = krb5_read_priv_message(context, ac, &sock, &data);
	    if(ret)
		krb5_err(context, 1, ret, "krb5_read_priv_message");
	}

	if(ret == HEIM_ERR_EOF || data.length == 0) {
	    if(!from_stdin) {
		data.data = NULL;
		data.length = 0;
		krb5_write_priv_message(context, ac, &sock, &data);
	    }
	    if(!print_dump) {
		ret = db->hdb_close(context, db);
		if(ret)
		    krb5_err(context, 1, ret, "db_close");
		ret = db->hdb_rename(context, db, database);
		if(ret)
		    krb5_err(context, 1, ret, "db_rename");
	    }
	    break;
	}
	memset(&entry, 0, sizeof(entry));
	ret = hdb_value2entry(context, &data, &entry.entry);
	krb5_data_free(&data);
	if(ret)
	    krb5_err(context, 1, ret, "hdb_value2entry");
	if(print_dump)
	    hdb_print_entry(context, db, &entry, stdout);
	else {
	    ret = db->hdb_store(context, db, 0, &entry);
	    if(ret == HDB_ERR_EXISTS) {
		char *s;
		ret = krb5_unparse_name(context, entry.entry.principal, &s);
		if (ret)
		    s = strdup("unparseable name");
		krb5_warnx(context, "Entry exists: %s", s);
		free(s);
	    } else if(ret)
		krb5_err(context, 1, ret, "db_store");
	    else
		nprincs++;
	}
	hdb_free_entry(context, &entry);
    }
    if (!print_dump)
	krb5_log(context, fac, 0, "Received %d principals", nprincs);

    if (inetd_flag == 0)
	rk_closesocket(sock);

    exit(0);
}
コード例 #19
0
ファイル: rlm_krb5.c プロジェクト: rssh/freeradius-server
/*
 *  validate user/pass (Heimdal)
 */
static int krb5_auth(void *instance, REQUEST *request)
{
	rlm_krb5_t *inst = instance;

	krb5_error_code ret;
	krb5_ccache id;
	krb5_principal userP;

	krb5_context context = *(inst->context); /* copy data */
	const char *user, *pass;

	char service[SERVICE_NAME_LEN] = "host";
	char *server_name = NULL;
	char *princ_name;

	krb5_verify_opt krb_verify_options;
	krb5_keytab keytab;

	if (inst->service_princ != NULL) {
		server_name = strchr(inst->service_princ, '/');
		if (server_name != NULL) {
			*server_name = '\0';
		}

		strlcpy(service, inst->service_princ, sizeof(service));
		if (server_name != NULL) {
			*server_name = '/';
			server_name++;
		}
	}

	/*
	 *  We can only authenticate user requests which HAVE
	 *  a User-Name attribute.
	 */
	if (!request->username) {
		radlog(L_AUTH, "rlm_krb5: Attribute \"User-Name\" is required for authentication.");
		
		return RLM_MODULE_INVALID;
	}

	/*
	 *  We can only authenticate user requests which HAVE
	 *  a User-Password attribute.
	 */
	if (!request->password) {
		radlog(L_AUTH, "rlm_krb5: Attribute \"User-Password\" is required for authentication.");
		
		return RLM_MODULE_INVALID;
	}

	/*
	 *  Ensure that we're being passed a plain-text password,
	 *  and not anything else.
	 */
	if (request->password->attribute != PW_USER_PASSWORD) {
		radlog(L_AUTH, "rlm_krb5: Attribute \"User-Password\" is required for authentication.  Cannot use \"%s\".", request->password->name);
		
		return RLM_MODULE_INVALID;
	}

	user = request->username->vp_strvalue;
	pass = request->password->vp_strvalue;

	ret = krb5_parse_name(context, user, &userP);
	if (ret) {
		radlog(L_AUTH, "rlm_krb5: [%s] krb5_parse_name failed: %s",
		       user, error_message(ret));
		       
		return RLM_MODULE_REJECT;
	}

	/*
	 *  Heimdal krb5 verification.
	 */
	 
	/*
	 *  The following bit allows us to also log user/instance@REALM if someone
	 *  logs in using an instance.
	 */
	ret = krb5_unparse_name(context, userP, &princ_name);
	if (ret != 0) {
		radlog(L_AUTH, "rlm_krb5: Unparsable name");
	} else {
		radlog(L_AUTH, "rlm_krb5: Parsed name is: %s", princ_name);
		free(princ_name);
	}

	krb5_cc_default(context, &id);

	/*
	 *  Set up krb5_verify_user options.
	 */
	krb5_verify_opt_init(&krb_verify_options);
	krb5_verify_opt_set_ccache(&krb_verify_options, id);

	/*
	 *  Resolve keytab name. This allows us to use something other than
	 *  the default system keytab
	 */
	if (inst->keytab != NULL) {
		ret = krb5_kt_resolve(context, inst->keytab, &keytab);
		if (ret) {
			radlog(L_AUTH, "rlm_krb5: unable to resolve keytab %s: %s",
			       inst->keytab, error_message(ret));
			krb5_kt_close(context, keytab);
			
			return RLM_MODULE_REJECT;
		}
		
		krb5_verify_opt_set_keytab(&krb_verify_options, keytab);
	}

	/*
	 *  Verify aquired credentials against the keytab.
	 */
	krb5_verify_opt_set_secure(&krb_verify_options, 1);

	/*
	 *  Allow us to use an arbitrary service name.
	 */
	krb5_verify_opt_set_service(&krb_verify_options, service);

	/* 
	 *  Verify the user, using the above set options.
	 */
	ret = krb5_verify_user_opt(context, userP, pass, &krb_verify_options);

	/*
	 *  We are done with the keytab, close it.
	 */
	krb5_kt_close(context, keytab);

	if (ret == 0)
		return RLM_MODULE_OK;

	radlog(L_AUTH, "rlm_krb5: failed verify_user: %s (%s@%s)",
	       error_message(ret),
	       *userP->name.name_string.val,
	       userP->realm);

	return RLM_MODULE_REJECT;
}
コード例 #20
0
ファイル: kinit.c プロジェクト: Kendra123/heimdal
static krb5_error_code
get_new_tickets(krb5_context context,
		krb5_principal principal,
		krb5_ccache ccache,
		krb5_deltat ticket_life,
		int interactive)
{
    krb5_error_code ret;
    krb5_get_init_creds_opt *opt;
    krb5_creds cred;
    char passwd[256];
    krb5_deltat start_time = 0;
    krb5_deltat renew = 0;
    const char *renewstr = NULL;
    krb5_enctype *enctype = NULL;
    krb5_ccache tempccache;
    krb5_keytab kt = NULL;
    krb5_init_creds_context ctx;
#ifndef NO_NTLM
    struct ntlm_buf ntlmkey;
    memset(&ntlmkey, 0, sizeof(ntlmkey));
#endif
    passwd[0] = '\0';

    if (password_file) {
	FILE *f;

	if (strcasecmp("STDIN", password_file) == 0)
	    f = stdin;
	else
	    f = fopen(password_file, "r");
	if (f == NULL)
	    krb5_errx(context, 1, "Failed to open the password file %s",
		      password_file);

	if (fgets(passwd, sizeof(passwd), f) == NULL)
	    krb5_errx(context, 1,
		      N_("Failed to read password from file %s", ""),
		      password_file);
	if (f != stdin)
	    fclose(f);
	passwd[strcspn(passwd, "\n")] = '\0';
    }

#ifdef __APPLE__
    if (passwd[0] == '\0') {
	const char *realm;
	OSStatus osret;
	UInt32 length;
	void *buffer;
	char *name;

	realm = krb5_principal_get_realm(context, principal);

	ret = krb5_unparse_name_flags(context, principal,
				      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
	if (ret)
	    goto nopassword;

	osret = SecKeychainFindGenericPassword(NULL, strlen(realm), realm,
					       strlen(name), name,
					       &length, &buffer, NULL);
	free(name);
	if (osret == noErr && length < sizeof(passwd) - 1) {
	    memcpy(passwd, buffer, length);
	    passwd[length] = '\0';
	}
    nopassword:
	do { } while(0);
    }
#endif

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

    ret = krb5_get_init_creds_opt_alloc(context, &opt);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    krb5_get_init_creds_opt_set_default_flags(context, "kinit",
	krb5_principal_get_realm(context, principal), opt);

    if (forwardable_flag != -1)
	krb5_get_init_creds_opt_set_forwardable(opt, forwardable_flag);
    if (proxiable_flag != -1)
	krb5_get_init_creds_opt_set_proxiable(opt, proxiable_flag);
    if (anonymous_flag)
	krb5_get_init_creds_opt_set_anonymous(opt, anonymous_flag);
    if (pac_flag != -1)
	krb5_get_init_creds_opt_set_pac_request(context, opt,
						pac_flag ? TRUE : FALSE);
    if (canonicalize_flag)
	krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE);
    if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag)
	krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
    if (pk_user_id || ent_user_id || anonymous_flag) {
	ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
						 principal,
						 pk_user_id,
						 pk_x509_anchors,
						 NULL,
						 NULL,
						 pk_use_enckey ? 2 : 0 |
						 anonymous_flag ? 4 : 0,
						 krb5_prompter_posix,
						 NULL,
						 passwd);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
	if (ent_user_id)
	    krb5_get_init_creds_opt_set_pkinit_user_certs(context, opt, ent_user_id);
    }

    if (addrs_flag != -1)
	krb5_get_init_creds_opt_set_addressless(context, opt,
						addrs_flag ? FALSE : TRUE);

    if (renew_life == NULL && renewable_flag)
	renewstr = "1 month";
    if (renew_life)
	renewstr = renew_life;
    if (renewstr) {
	renew = parse_time(renewstr, "s");
	if (renew < 0)
	    errx(1, "unparsable time: %s", renewstr);

	krb5_get_init_creds_opt_set_renew_life(opt, renew);
    }

    if (ticket_life != 0)
	krb5_get_init_creds_opt_set_tkt_life(opt, ticket_life);

    if (start_str) {
	int tmp = parse_time(start_str, "s");
	if (tmp < 0)
	    errx(1, N_("unparsable time: %s", ""), start_str);

	start_time = tmp;
    }

    if (etype_str.num_strings) {
	int i;

	enctype = malloc(etype_str.num_strings * sizeof(*enctype));
	if (enctype == NULL)
	    errx(1, "out of memory");
	for(i = 0; i < etype_str.num_strings; i++) {
	    ret = krb5_string_to_enctype(context,
					 etype_str.strings[i],
					 &enctype[i]);
	    if (ret)
		errx(1, "unrecognized enctype: %s", etype_str.strings[i]);
	}
	krb5_get_init_creds_opt_set_etype_list(opt, enctype,
					       etype_str.num_strings);
    }

    ret = krb5_init_creds_init(context, principal, krb5_prompter_posix, NULL, start_time, opt, &ctx);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_init");

    if (server_str) {
	ret = krb5_init_creds_set_service(context, ctx, server_str);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_service");
    }

    if (fast_armor_cache_string) {
	krb5_ccache fastid;
	
	ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve(FAST cache)");
	
	ret = krb5_init_creds_set_fast_ccache(context, ctx, fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_fast_ccache");
    }

    if (use_keytab || keytab_str) {

	if (keytab_str)
	    ret = krb5_kt_resolve(context, keytab_str, &kt);
	else
	    ret = krb5_kt_default(context, &kt);
	if (ret)
	    krb5_err(context, 1, ret, "resolving keytab");

	ret = krb5_init_creds_set_keytab(context, ctx, kt);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_keytab");

    } else if (pk_user_id || ent_user_id || anonymous_flag) {

    } else if (!interactive) {
	static int already_warned = 0;

	if (!already_warned)
	    krb5_warnx(context, "Not interactive, failed to get "
	      "initial ticket");
	krb5_get_init_creds_opt_free(context, opt);
	already_warned = 1;
	return 0;
    } else {

	if (passwd[0] == '\0') {
	    char *p, *prompt;
	    int aret = 0;

	    ret = krb5_unparse_name(context, principal, &p);
	    if (!ret) {
		aret = asprintf(&prompt, N_("%s's Password: "******""), p);
		free(p);
	    }
	    if (ret || aret == -1)
		errx(1, "failed to generate passwd prompt: not enough memory");

	    if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
		memset(passwd, 0, sizeof(passwd));
		errx(1, "failed to read password");
	    }
	    free(prompt);
	}

	if (passwd[0]) {
	    ret = krb5_init_creds_set_password(context, ctx, passwd);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_init_creds_set_password");
	}
    }

    ret = krb5_init_creds_get(context, ctx);

#ifndef NO_NTLM
    if (ntlm_domain && passwd[0])
	heim_ntlm_nt_key(passwd, &ntlmkey);
#endif
    memset(passwd, 0, sizeof(passwd));

    switch(ret){
    case 0:
	break;
    case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */
	exit(1);
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KRB_AP_ERR_MODIFIED:
    case KRB5KDC_ERR_PREAUTH_FAILED:
    case KRB5_GET_IN_TKT_LOOP:
	krb5_errx(context, 1, N_("Password incorrect", ""));
	break;
    case KRB5KRB_AP_ERR_V4_REPLY:
	krb5_errx(context, 1, N_("Looks like a Kerberos 4 reply", ""));
	break;
    default:
	krb5_err(context, 1, ret, "krb5_get_init_creds");
    }

    krb5_process_last_request(context, opt, ctx);

    ret = krb5_init_creds_get_creds(context, ctx, &cred);
    if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_get_creds");

    if (ticket_life != 0) {
	if (abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) {
	    char life[64];
	    unparse_time_approx(cred.times.endtime - cred.times.starttime,
				life, sizeof(life));
	    krb5_warnx(context, N_("NOTICE: ticket lifetime is %s", ""), life);
	}
    }
    if (renew_life) {
	if (abs(cred.times.renew_till - cred.times.starttime - renew) > 30) {
	    char life[64];
	    unparse_time_approx(cred.times.renew_till - cred.times.starttime,
				life, sizeof(life));
	    krb5_warnx(context,
		       N_("NOTICE: ticket renewable lifetime is %s", ""),
		       life);
	}
    }

    ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache),
			     NULL, &tempccache);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_new_unique");

    ret = krb5_init_creds_store(context, ctx, tempccache);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_store");

    krb5_init_creds_free(context, ctx);

    ret = krb5_cc_move(context, tempccache, ccache);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_move");

    if (switch_cache_flags)
	krb5_cc_switch(context, ccache);

#ifndef NO_NTLM
    if (ntlm_domain && ntlmkey.data)
	store_ntlmkey(context, ccache, ntlm_domain, &ntlmkey);
#endif

    if (ok_as_delegate_flag || windows_flag || use_referrals_flag) {
	unsigned char d = 0;
	krb5_data data;

	if (ok_as_delegate_flag || windows_flag)
	    d |= 1;
	if (use_referrals_flag || windows_flag)
	    d |= 2;

	data.length = 1;
	data.data = &d;

	krb5_cc_set_config(context, ccache, NULL, "realm-config", &data);
    }

    krb5_get_init_creds_opt_free(context, opt);

    if (kt)			
	krb5_kt_close(context, kt);
    if (enctype)
	free(enctype);

    return 0;
}
コード例 #21
0
ファイル: kstuff.c プロジェクト: davidben/zephyr
Code_t
ZCheckSrvAuthentication(ZNotice_t *notice,
			struct sockaddr_in *from,
			char *realm)
{
#ifdef HAVE_KRB5
    unsigned char *authbuf;
    krb5_principal princ;
    krb5_data packet;
    krb5_ticket *tkt;
    char *name;
    krb5_error_code result;
    krb5_principal server;
    krb5_keytab keytabid = 0;
    krb5_auth_context authctx;
    krb5_keyblock *keyblock;
    krb5_enctype enctype;
    krb5_cksumtype cksumtype;
    krb5_data cksumbuf;
    int valid;
    char *cksum0_base, *cksum1_base = NULL, *cksum2_base;
    char *x;
    unsigned char *asn1_data, *key_data, *cksum_data;
    int asn1_len, key_len, cksum0_len = 0, cksum1_len = 0, cksum2_len = 0;
    KRB5_AUTH_CON_FLAGS_TYPE acflags;
#ifdef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER
    krb5_authenticator *authenticator;
#define KRB5AUTHENT authenticator
#else
    krb5_authenticator authenticator;
#define KRB5AUTHENT &authenticator
#endif
    int len;
    char *sender;
    char rlmprincipal[MAX_PRINCIPAL_SIZE];

    if (!notice->z_auth)
        return ZAUTH_NO;

    /* Check for bogus authentication data length. */
    if (notice->z_authent_len <= 0) {
        syslog(LOG_DEBUG, "ZCheckSrvAuthentication: bogus authenticator length");
        return ZAUTH_FAILED;
    }

#ifdef HAVE_KRB4
    if (notice->z_ascii_authent[0] != 'Z' && realm == NULL)
      return ZCheckAuthentication4(notice, from);
#endif

    len = strlen(notice->z_ascii_authent)+1;
    authbuf = malloc(len);

    /* Read in the authentication data. */
    if (ZReadZcode((unsigned char *)notice->z_ascii_authent,
                   authbuf,
                   len, &len) == ZERR_BADFIELD) {
        syslog(LOG_DEBUG, "ZCheckSrvAuthentication: ZReadZcode: Improperly formatted field");
        return ZAUTH_FAILED;
    }

    if (realm == NULL) {
	sender = notice->z_sender;
    } else {
	(void) snprintf(rlmprincipal, MAX_PRINCIPAL_SIZE, "%s/%s@%s", SERVER_SERVICE,
			SERVER_INSTANCE, realm);
	sender = rlmprincipal;
    }

    packet.length = len;
    packet.data = (char *)authbuf;

    result = krb5_kt_resolve(Z_krb5_ctx,
                        keytab_file, &keytabid);
    if (result) {
        free(authbuf);
        syslog(LOG_DEBUG, "ZCheckSrvAuthentication: krb5_kt_resolve: %s", error_message(result));
        return ZAUTH_FAILED;
    }

    /* HOLDING: authbuf, keytabid */
    /* Create the auth context */
    result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
    if (result) {
        krb5_kt_close(Z_krb5_ctx, keytabid);
        free(authbuf);
        syslog(LOG_DEBUG, "ZCheckSrvAuthentication: krb5_auth_con_init: %s", error_message(result));
        return ZAUTH_FAILED;
    }

    /* HOLDING: authbuf, keytabid, authctx */
    result = krb5_auth_con_getflags(Z_krb5_ctx, authctx, &acflags);
    if (result) {
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        krb5_kt_close(Z_krb5_ctx, keytabid);
        free(authbuf);
        syslog(LOG_DEBUG, "ZCheckSrvAuthentication: krb5_auth_con_getflags: %s", error_message(result));
        return ZAUTH_FAILED;
    }

    acflags &= ~KRB5_AUTH_CONTEXT_DO_TIME;

    result = krb5_auth_con_setflags(Z_krb5_ctx, authctx, acflags);
    if (result) {
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        krb5_kt_close(Z_krb5_ctx, keytabid);
        free(authbuf);
        syslog(LOG_DEBUG, "ZCheckSrvAuthentication: krb5_auth_con_setflags: %s", error_message(result));
        return ZAUTH_FAILED;
    }

    result = krb5_build_principal(Z_krb5_ctx, &server, strlen(__Zephyr_realm),
				  __Zephyr_realm, SERVER_SERVICE,
				  SERVER_INSTANCE, NULL);
    if (!result) {
        result = krb5_rd_req(Z_krb5_ctx, &authctx, &packet, server,
                             keytabid, NULL, &tkt);
	krb5_free_principal(Z_krb5_ctx, server);
    }
    krb5_kt_close(Z_krb5_ctx, keytabid);

    /* HOLDING: authbuf, authctx */
    if (result) {
        if (result == KRB5KRB_AP_ERR_REPEAT)
            syslog(LOG_DEBUG, "ZCheckSrvAuthentication: k5 auth failed: %s",
                   error_message(result));
        else
            syslog(LOG_WARNING,"ZCheckSrvAuthentication: k5 auth failed: %s",
                   error_message(result));
        free(authbuf);
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        return ZAUTH_FAILED;
    }

    /* HOLDING: authbuf, authctx, tkt */

    if (tkt == 0 || !Z_tktprincp(tkt)) {
        if (tkt)
            krb5_free_ticket(Z_krb5_ctx, tkt);
        free(authbuf);
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        syslog(LOG_WARNING, "ZCheckSrvAuthentication: No Ticket");
        return ZAUTH_FAILED;
    }

    princ = Z_tktprinc(tkt);

    if (princ == 0) {
        krb5_free_ticket(Z_krb5_ctx, tkt);
        free(authbuf);
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        syslog(LOG_WARNING, "ZCheckSrvAuthentication: No... Ticket?");
        return ZAUTH_FAILED;
    }

    /* HOLDING: authbuf, authctx, tkt */
    result = krb5_unparse_name(Z_krb5_ctx, princ, &name);
    if (result) {
        syslog(LOG_WARNING, "ZCheckSrvAuthentication: krb5_unparse_name failed: %s",
               error_message(result));
        free(authbuf);
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        krb5_free_ticket(Z_krb5_ctx, tkt);
        return ZAUTH_FAILED;
    }

    krb5_free_ticket(Z_krb5_ctx, tkt);

    /* HOLDING: authbuf, authctx, name */
    if (strcmp(name, sender)) {
        syslog(LOG_WARNING, "ZCheckSrvAuthentication: name mismatch: '%s' vs '%s'",
               name, sender);
        krb5_auth_con_free(Z_krb5_ctx, authctx);
#ifdef HAVE_KRB5_FREE_UNPARSED_NAME
        krb5_free_unparsed_name(Z_krb5_ctx, name);
#else
        free(name);
#endif
        free(authbuf);
        return ZAUTH_FAILED;
    }
#ifdef HAVE_KRB5_FREE_UNPARSED_NAME
    krb5_free_unparsed_name(Z_krb5_ctx, name);
#else
    free(name);
#endif
    free(authbuf);

    /* HOLDING: authctx */
    /* Get an authenticator so we can get the keyblock */
    result = krb5_auth_con_getauthenticator (Z_krb5_ctx, authctx,
    					     &authenticator);
    if (result) {
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        syslog(LOG_WARNING, "ZCheckSrvAuthentication: krb5_auth_con_getauthenticator failed: %s",
               error_message(result));
        return ZAUTH_FAILED;
    }

    /* HOLDING: authctx, authenticator */
    result = krb5_auth_con_getkey(Z_krb5_ctx, authctx, &keyblock);
    if (result) {
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
        syslog(LOG_WARNING, "ZCheckSrvAuthentication: krb5_auth_con_getkey failed: %s",
               error_message(result));
        return (ZAUTH_FAILED);
    }

    /* HOLDING: authctx, authenticator, keyblock */
    /* Figure out what checksum type to use */
    key_data = Z_keydata(keyblock);
    key_len = Z_keylen(keyblock);
    result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
    if (result) {
        krb5_free_keyblock(Z_krb5_ctx, keyblock);
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
        syslog(LOG_WARNING, "ZCheckSrvAuthentication: Z_ExtractEncCksum failed: %s",
               error_message(result));
        return (ZAUTH_FAILED);
    }
    /* HOLDING: authctx, authenticator, keyblock */

    if (realm == NULL)
	ZSetSession(keyblock);

    /* Assemble the things to be checksummed */
    /* first part is from start of packet through z_default_format:
     * - z_version
     * - z_num_other_fields
     * - z_kind
     * - z_uid
     * - z_port
     * - z_auth
     * - z_authent_len
     * - z_ascii_authent
     * - z_class
     * - z_class_inst
     * - z_opcode
     * - z_sender
     * - z_recipient
     * - z_default_format
     */
    cksum0_base = notice->z_packet;
    x           = notice->z_default_format;
    cksum0_len  = x + strlen(x) + 1 - cksum0_base;
    /* second part is from z_multinotice through other fields:
     * - z_multinotice
     * - z_multiuid
     * - z_sender_(sock)addr
     * - z_charset
     * - z_other_fields[]
     */
    if (notice->z_num_hdr_fields > 15 ) {
	cksum1_base = notice->z_multinotice;
	if (notice->z_num_other_fields)
	    x = notice->z_other_fields[notice->z_num_other_fields - 1];
	else {
	    /* see also ZCheckRealmAuthentication
	       and lib/ZCkZaut.c:ZCheckZcodeAuthentication  */
	    /* XXXXXXXXXXXXXXXXXXXXXXX */
	    if (notice->z_num_hdr_fields > 16)
		x = cksum1_base + strlen(cksum1_base) + 1; /* multinotice */
	    if (notice->z_num_hdr_fields > 17)
		x = x + strlen(x) + 1; /* multiuid */
	    if (notice->z_num_hdr_fields > 18)
		x = x + strlen(x) + 1; /* sender */
	}
	cksum1_len  = x + strlen(x) + 1 - cksum1_base; /* charset / extra field */
    }

    /* last part is the message body */
    cksum2_base = notice->z_message;
    cksum2_len  = notice->z_message_len;

    /*XXX we may wish to ditch this code someday?*/
    if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') &&
        key_len == 8 &&
        (enctype == (krb5_enctype)ENCTYPE_DES_CBC_CRC ||
         enctype == (krb5_enctype)ENCTYPE_DES_CBC_MD4 ||
         enctype == (krb5_enctype)ENCTYPE_DES_CBC_MD5)) {
      /* try old-format checksum (covers cksum0 only) */

      ZChecksum_t our_checksum;

      if (realm == NULL)
	  our_checksum = compute_checksum(notice, key_data);
      else
	  our_checksum = compute_rlm_checksum(notice, key_data);

      krb5_free_keyblock(Z_krb5_ctx, keyblock);
      krb5_auth_con_free(Z_krb5_ctx, authctx);
      krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);

      if (our_checksum == notice->z_checksum) {
          return ZAUTH_YES;
      } else {
          syslog(LOG_DEBUG, "ZCheckSrvAuthentication: des quad checksum mismatch");
          return ZAUTH_FAILED;
      }
    }

    /* HOLDING: authctx, authenticator */

    cksumbuf.length = cksum0_len + cksum1_len + cksum2_len;
    cksumbuf.data = malloc(cksumbuf.length);
    if (!cksumbuf.data) {
        krb5_free_keyblock(Z_krb5_ctx, keyblock);
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
        syslog(LOG_ERR, "ZCheckSrvAuthentication: malloc(cksumbuf.data): %m");
        return ZAUTH_FAILED;
    }
    /* HOLDING: authctx, authenticator, cksumbuf.data */

    cksum_data = (unsigned char *)cksumbuf.data;
    memcpy(cksum_data, cksum0_base, cksum0_len);
    if (cksum1_len)
	memcpy(cksum_data + cksum0_len, cksum1_base, cksum1_len);
    memcpy(cksum_data + cksum0_len + cksum1_len,
           cksum2_base, cksum2_len);

    /* decode zcoded checksum */
    /* The encoded form is always longer than the original */
    asn1_len = strlen(notice->z_ascii_checksum) + 1;
    asn1_data = malloc(asn1_len);
    if (!asn1_data) {
        krb5_free_keyblock(Z_krb5_ctx, keyblock);
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
        free(cksumbuf.data);
        syslog(LOG_ERR, "ZCheckSrvAuthentication: malloc(asn1_data): %m");
        return ZAUTH_FAILED;
    }
    /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */
    result = ZReadZcode((unsigned char *)notice->z_ascii_checksum,
                        asn1_data, asn1_len, &asn1_len);
    if (result != ZERR_NONE) {
        krb5_free_keyblock(Z_krb5_ctx, keyblock);
        krb5_auth_con_free(Z_krb5_ctx, authctx);
        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
        free(asn1_data);
        free(cksumbuf.data);
        syslog(LOG_WARNING, "ZCheckSrvAuthentication: ZReadZcode: %s",
               error_message(result));
        return ZAUTH_FAILED;
    }
    /* HOLDING: asn1_data, cksumbuf.data, authctx, authenticator */

    valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype,
				Z_KEYUSAGE_CLT_CKSUM,
				asn1_data, asn1_len);

    /* XXX compatibility with unreleased interrealm krb5; drop in 3.1 */
    if (!valid && realm)
	valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype,
				    Z_KEYUSAGE_SRV_CKSUM,
				    asn1_data, asn1_len);

    free(asn1_data);
    krb5_auth_con_free(Z_krb5_ctx, authctx);
    krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
    krb5_free_keyblock(Z_krb5_ctx, keyblock);
    free(cksumbuf.data);

    if (valid) {
        return ZAUTH_YES;
    } else {
        syslog(LOG_DEBUG, "ZCheckSrvAuthentication: Z_krb5_verify_cksum: failed");
        return ZAUTH_FAILED;
    }
#else
    return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO;
#endif
}
コード例 #22
0
ファイル: list.c プロジェクト: cyrilmagsuci/freebsd
static int
do_list(struct list_options *opt, const char *keytab_str)
{
    krb5_error_code ret;
    krb5_keytab keytab;
    krb5_keytab_entry entry;
    krb5_kt_cursor cursor;
    rtbl_t table;

    /* XXX specialcase the ANY type */
    if(strncasecmp(keytab_str, "ANY:", 4) == 0) {
        int flag = 0;
        char buf[1024];
        keytab_str += 4;
        ret = 0;
        while (strsep_copy((const char**)&keytab_str, ",",
                           buf, sizeof(buf)) != -1) {
            if(flag)
                printf("\n");
            if(do_list(opt, buf))
                ret = 1;
            flag = 1;
        }
        return ret;
    }

    ret = krb5_kt_resolve(context, keytab_str, &keytab);
    if (ret) {
        krb5_warn(context, ret, "resolving keytab %s", keytab_str);
        return ret;
    }

    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    if(ret) {
        krb5_warn(context, ret, "krb5_kt_start_seq_get %s", keytab_str);
        krb5_kt_close(context, keytab);
        return ret;
    }

    printf ("%s:\n\n", keytab_str);

    table = rtbl_create();
    rtbl_add_column_by_id(table, 0, "Vno", RTBL_ALIGN_RIGHT);
    rtbl_add_column_by_id(table, 1, "Type", 0);
    rtbl_add_column_by_id(table, 2, "Principal", 0);
    if (opt->timestamp_flag)
        rtbl_add_column_by_id(table, 3, "Date", 0);
    if(opt->keys_flag)
        rtbl_add_column_by_id(table, 4, "Key", 0);
    rtbl_add_column_by_id(table, 5, "Aliases", 0);
    rtbl_set_separator(table, "  ");

    while(krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0) {
        char buf[1024], *s;

        snprintf(buf, sizeof(buf), "%d", entry.vno);
        rtbl_add_column_entry_by_id(table, 0, buf);

        ret = krb5_enctype_to_string(context,
                                     entry.keyblock.keytype, &s);
        if (ret != 0) {
            snprintf(buf, sizeof(buf), "unknown (%d)", entry.keyblock.keytype);
            rtbl_add_column_entry_by_id(table, 1, buf);
        } else {
            rtbl_add_column_entry_by_id(table, 1, s);
            free(s);
        }

        krb5_unparse_name_fixed(context, entry.principal, buf, sizeof(buf));
        rtbl_add_column_entry_by_id(table, 2, buf);

        if (opt->timestamp_flag) {
            krb5_format_time(context, entry.timestamp, buf,
                             sizeof(buf), FALSE);
            rtbl_add_column_entry_by_id(table, 3, buf);
        }
        if(opt->keys_flag) {
            size_t i;
            s = malloc(2 * entry.keyblock.keyvalue.length + 1);
            if (s == NULL) {
                krb5_warnx(context, "malloc failed");
                ret = ENOMEM;
                goto out;
            }
            for(i = 0; i < entry.keyblock.keyvalue.length; i++)
                snprintf(s + 2 * i, 3, "%02x",
                         ((unsigned char*)entry.keyblock.keyvalue.data)[i]);
            rtbl_add_column_entry_by_id(table, 4, s);
            free(s);
        }
        if (entry.aliases) {
            unsigned int i;
            struct rk_strpool *p = NULL;

            for (i = 0; i< entry.aliases->len; i++) {
                krb5_unparse_name_fixed(context, entry.principal, buf, sizeof(buf));
                rk_strpoolprintf(p, "%s%s", buf,
                                 i + 1 < entry.aliases->len ? ", " : "");

            }
            rtbl_add_column_entry_by_id(table, 5, rk_strpoolcollect(p));
        }

        krb5_kt_free_entry(context, &entry);
    }
    ret = krb5_kt_end_seq_get(context, keytab, &cursor);
    rtbl_format(table, stdout);

out:
    rtbl_destroy(table);

    krb5_kt_close(context, keytab);
    return ret;
}
コード例 #23
0
int Condor_Auth_Kerberos :: authenticate_server_kerberos()
{
    krb5_error_code   code;
    krb5_flags        flags = 0;
    krb5_data         request, reply;
    priv_state        priv;
    krb5_keytab       keytab = 0;
    int               message, rc = FALSE;
    krb5_ticket *     ticket = NULL;

    request.data = 0;
    reply.data   = 0;
    
    keytabName_ = param(STR_KERBEROS_SERVER_KEYTAB);

    //------------------------------------------
    // Getting keytab info
    //------------------------------------------
    if (keytabName_) {
        code = krb5_kt_resolve(krb_context_, keytabName_, &keytab);
    }
    else {
        code = krb5_kt_default(krb_context_, &keytab);
    }
    
    if (code) {
        dprintf( D_ALWAYS, "1: Kerberos server authentication error:%s\n",
				 error_message(code) );
        goto error;
    }
    
    //------------------------------------------
    // Get te KRB_AP_REQ message
    //------------------------------------------
    if(read_request(&request) == FALSE) {
        dprintf( D_ALWAYS, "KERBEROS: Server is unable to read request\n" );
        goto error;
    }
    
	dprintf( D_SECURITY, "Reading kerberos request object (krb5_rd_req)\n");

	dprintf_krb5_principal( D_FULLDEBUG, "KERBEROS: krb_principal_ is '%s'\n", krb_principal_);

 priv = set_root_priv();   // Get the old privilige
    
    if ((code = krb5_rd_req(krb_context_,
                           &auth_context_,
                           &request,
                           //krb_principal_,
						   NULL,
                           keytab,
                           &flags,
                           &ticket))) {
        set_priv(priv);   // Reset
        dprintf( D_ALWAYS, "2: Kerberos server authentication error:%s\n",
				 error_message(code) );
        goto error;
    }
    set_priv(priv);   // Reset
    
	dprintf ( D_FULLDEBUG, "KERBEROS: krb5_rd_req done.\n");

    //------------------------------------------
    // See if mutual authentication is required
    //------------------------------------------
    if (flags & AP_OPTS_MUTUAL_REQUIRED) {
        if ((code = krb5_mk_rep(krb_context_, auth_context_, &reply))) {
            dprintf( D_ALWAYS, "3: Kerberos server authentication error:%s\n",
					 error_message(code) );
            goto error;
        }

        mySock_->encode();
        message = KERBEROS_MUTUAL;
        if (!mySock_->code(message) || !mySock_->end_of_message()) {
            goto error;
        }

        // send the message
        if (send_request(&reply) != KERBEROS_GRANT) {
            goto cleanup;
        }
    }
    
    //------------------------------------------
    // extract client addresses
    //------------------------------------------
    if (ticket->enc_part2->caddrs) {
        struct in_addr in;
        memcpy(&(in.s_addr), ticket->enc_part2->caddrs[0]->contents, sizeof(in_addr));
        
        setRemoteHost(inet_ntoa(in));
    
        dprintf(D_SECURITY, "Client address is %s\n", getRemoteHost());
    }    

    // First, map the name, this has to take place before receive_tgt_creds!
    if (!map_kerberos_name(&(ticket->enc_part2->client))) {
        dprintf(D_SECURITY, "Unable to map Kerberos name\n");
        goto error;
    }

    // copy the session key
    if ((code = krb5_copy_keyblock(krb_context_, 
                                  ticket->enc_part2->session, 
                                  &sessionKey_))){
        dprintf(D_SECURITY, "4: Kerberos server authentication error:%s\n", error_message(code));
        goto error;
    }
    
    // Next, see if we need client to forward the credential as well
    if (receive_tgt_creds(ticket)) {
        goto cleanup;
    }
    
    //------------------------------------------
    // We are now authenticated!
    //------------------------------------------
    dprintf(D_SECURITY, "User %s is now authenticated!\n", getRemoteUser());
    
    rc = TRUE;
    
    goto cleanup;
    
 error:
    message = KERBEROS_DENY;
    
    mySock_->encode();
    if ((!mySock_->code(message)) || (!mySock_->end_of_message())) {
        dprintf( D_ALWAYS, "KERBEROS: Failed to send response message!\n" );
    }
    
 cleanup:
    
    //------------------------------------------
    // Free up some stuff
    //------------------------------------------
    if (ticket) {
        krb5_free_ticket(krb_context_, ticket);
    }
    
    if (keytab) {
        krb5_kt_close(krb_context_, keytab);
    }
    //------------------------------------------
    // Free it for now, in the future, we might 
    // need this for future secure transctions.
    //------------------------------------------
    if (request.data) {
        free(request.data);
    }
    
    if (reply.data) {
        free(reply.data);
    }

    return rc;
}
コード例 #24
0
ファイル: klist.c プロジェクト: INNOAUS/krb5
static void
do_keytab(const char *name)
{
    krb5_error_code ret;
    krb5_keytab kt;
    krb5_keytab_entry entry;
    krb5_kt_cursor cursor;
    unsigned int i;
    char buf[BUFSIZ]; /* Hopefully large enough for any type */
    char *pname;

    if (name == NULL && use_client_keytab) {
        ret = krb5_kt_client_default(context, &kt);
        if (ret) {
            com_err(progname, ret, _("while getting default client keytab"));
            exit(1);
        }
    } else if (name == NULL) {
        ret = krb5_kt_default(context, &kt);
        if (ret) {
            com_err(progname, ret, _("while getting default keytab"));
            exit(1);
        }
    } else {
        ret = krb5_kt_resolve(context, name, &kt);
        if (ret) {
            com_err(progname, ret, _("while resolving keytab %s"), name);
            exit(1);
        }
    }

    ret = krb5_kt_get_name(context, kt, buf, BUFSIZ);
    if (ret) {
        com_err(progname, ret, _("while getting keytab name"));
        exit(1);
    }

    printf("Keytab name: %s\n", buf);

    ret = krb5_kt_start_seq_get(context, kt, &cursor);
    if (ret) {
        com_err(progname, ret, _("while starting keytab scan"));
        exit(1);
    }

    /* XXX Translating would disturb table alignment; skip for now. */
    if (show_time) {
        printf("KVNO Timestamp");
        fillit(stdout, timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
        printf("Principal\n");
        printf("---- ");
        fillit(stdout, timestamp_width, (int) '-');
        printf(" ");
        fillit(stdout, 78 - timestamp_width - sizeof("KVNO"), (int) '-');
        printf("\n");
    } else {
        printf("KVNO Principal\n");
        printf("---- ------------------------------------------------"
               "--------------------------\n");
    }

    while ((ret = krb5_kt_next_entry(context, kt, &entry, &cursor)) == 0) {
        ret = krb5_unparse_name(context, entry.principal, &pname);
        if (ret) {
            com_err(progname, ret, _("while unparsing principal name"));
            exit(1);
        }
        printf("%4d ", entry.vno);
        if (show_time) {
            printtime(entry.timestamp);
            printf(" ");
        }
        printf("%s", pname);
        if (show_etype)
            printf(" (%s) " , etype_string(entry.key.enctype));
        if (show_keys) {
            printf(" (0x");
            for (i = 0; i < entry.key.length; i++)
                printf("%02x", entry.key.contents[i]);
            printf(")");
        }
        printf("\n");
        krb5_free_unparsed_name(context, pname);
        krb5_free_keytab_entry_contents(context, &entry);
    }
    if (ret && ret != KRB5_KT_END) {
        com_err(progname, ret, _("while scanning keytab"));
        exit(1);
    }
    ret = krb5_kt_end_seq_get(context, kt, &cursor);
    if (ret) {
        com_err(progname, ret, _("while ending keytab scan"));
        exit(1);
    }
    exit(0);
}
コード例 #25
0
ファイル: cifs.upcall.c プロジェクト: MageSlayer/cifs-utils
static char *
init_cc_from_keytab(const char *keytab_name, const char *user)
{
	krb5_context context = NULL;
	krb5_error_code ret;
	krb5_creds my_creds;
	krb5_keytab keytab = NULL;
	krb5_principal me = NULL;
	krb5_ccache cc = NULL;
	char *ccname = NULL;

	memset((char *) &my_creds, 0, sizeof(my_creds));

	ret = krb5_init_context(&context);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_init_context: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_kt_resolve(context, keytab_name, &keytab);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_kt_resolve: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_parse_name(context, user, &me);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_parse_name: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_get_init_creds_keytab(context, &my_creds, me,
			keytab, 0, NULL, NULL);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_get_init_creds_keytab: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_cc_default(context, &cc);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_cc_default: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_cc_initialize(context, cc, me);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_cc_initialize: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_cc_store_cred(context, cc, &my_creds);
	if (ret)
		syslog(LOG_DEBUG, "krb5_cc_store_cred: %d", (int)ret);

	ccname = strdup(krb5_cc_default_name(context));
	if (ccname == NULL)
		syslog(LOG_ERR, "Unable to allocate memory");
icfk_cleanup:
	my_creds.client = 0;
	krb5_free_cred_contents(context, &my_creds);

	if (me)
		krb5_free_principal(context, me);
	if (cc)
		krb5_cc_close(context, cc);
	if (keytab)
		krb5_kt_close(context, keytab);
	if (context)
		krb5_free_context(context);
	return ccname;
}
コード例 #26
0
ファイル: client_init.c プロジェクト: BeaverWorld/krb5
/* Perform one iteration of attempting to get credentials.  This includes
 * searching existing ccache for requested service if INIT_CREDS. */
static kadm5_ret_t
gic_iter(kadm5_server_handle_t handle, enum init_type init_type,
         krb5_ccache ccache, krb5_principal client, char *pass, char *svcname,
         char *realm, krb5_principal *server_out)
{
    kadm5_ret_t code;
    krb5_context ctx;
    krb5_keytab kt;
    krb5_get_init_creds_opt *opt = NULL;
    krb5_creds mcreds, outcreds;

    *server_out = NULL;
    ctx = handle->context;
    kt = NULL;
    memset(&opt, 0, sizeof(opt));
    memset(&mcreds, 0, sizeof(mcreds));
    memset(&outcreds, 0, sizeof(outcreds));

    /* Credentials for kadmin don't need to be forwardable or proxiable. */
    if (init_type != INIT_CREDS) {
        code = krb5_get_init_creds_opt_alloc(ctx, &opt);
        krb5_get_init_creds_opt_set_forwardable(opt, 0);
        krb5_get_init_creds_opt_set_proxiable(opt, 0);
        krb5_get_init_creds_opt_set_out_ccache(ctx, opt, ccache);
        if (init_type == INIT_ANONYMOUS)
            krb5_get_init_creds_opt_set_anonymous(opt, 1);
    }

    if (init_type == INIT_PASS || init_type == INIT_ANONYMOUS) {
        code = krb5_get_init_creds_password(ctx, &outcreds, client, pass,
                                            krb5_prompter_posix,
                                            NULL, 0, svcname, opt);
        if (code)
            goto error;
    } else if (init_type == INIT_SKEY) {
        if (pass) {
            code = krb5_kt_resolve(ctx, pass, &kt);
            if (code)
                goto error;
        }
        code = krb5_get_init_creds_keytab(ctx, &outcreds, client, kt,
                                          0, svcname, opt);
        if (pass)
            krb5_kt_close(ctx, kt);
        if (code)
            goto error;
    } else if (init_type == INIT_CREDS) {
        mcreds.client = client;
        code = krb5_parse_name_flags(ctx, svcname,
                                     KRB5_PRINCIPAL_PARSE_IGNORE_REALM,
                                     &mcreds.server);
        if (code)
            goto error;
        code = krb5_set_principal_realm(ctx, mcreds.server, realm);
        if (code)
            goto error;
        code = krb5_cc_retrieve_cred(ctx, ccache, 0,
                                     &mcreds, &outcreds);
        krb5_free_principal(ctx, mcreds.server);
        if (code)
            goto error;
    } else {
        code = EINVAL;
        goto error;
    }

    /* Steal the server principal of the creds we acquired and return it to the
     * caller, which needs to knows what service to authenticate to. */
    *server_out = outcreds.server;
    outcreds.server = NULL;

error:
    krb5_free_cred_contents(ctx, &outcreds);
    if (opt)
        krb5_get_init_creds_opt_free(ctx, opt);
    return code;
}
コード例 #27
0
ファイル: init_c.c プロジェクト: alepharchives/bitrig
static krb5_error_code
get_new_cache(krb5_context context,
	      krb5_principal client,
	      const char *password,
	      krb5_prompter_fct prompter,
	      const char *keytab,
	      const char *server_name,
	      krb5_ccache *ret_cache)
{
    krb5_error_code ret;
    krb5_creds cred;
    krb5_get_init_creds_opt *opt;
    krb5_ccache id;
    
    ret = krb5_get_init_creds_opt_alloc (context, &opt);
    if (ret)
	return ret;

    krb5_get_init_creds_opt_set_default_flags(context, "kadmin", 
					      krb5_principal_get_realm(context, 
								       client), 
					      opt);


    krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
    krb5_get_init_creds_opt_set_proxiable (opt, FALSE);

    if(password == NULL && prompter == NULL) {
	krb5_keytab kt;
	if(keytab == NULL)
	    ret = krb5_kt_default(context, &kt);
	else
	    ret = krb5_kt_resolve(context, keytab, &kt);
	if(ret) {
	    krb5_get_init_creds_opt_free(opt);
	    return ret;
	}
	ret = krb5_get_init_creds_keytab (context,
					  &cred,
					  client,
					  kt,
					  0,
					  server_name,
					  opt);
	krb5_kt_close(context, kt);
    } else {
	ret = krb5_get_init_creds_password (context,
					    &cred,
					    client,
					    password,
					    prompter,
					    NULL,
					    0,
					    server_name,
					    opt);
    }
    krb5_get_init_creds_opt_free(opt);
    switch(ret){
    case 0:
	break;
    case KRB5_LIBOS_PWDINTR:	/* don't print anything if it was just C-c:ed */
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KRB_AP_ERR_MODIFIED:
	return KADM5_BAD_PASSWORD;
    default:
	return ret;
    }
    ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
    if(ret)
	return ret;
    ret = krb5_cc_initialize (context, id, cred.client);
    if (ret)
	return ret;
    ret = krb5_cc_store_cred (context, id, &cred);
    if (ret)
	return ret;
    krb5_free_cred_contents (context, &cred);
    *ret_cache = id;
    return 0;
}
コード例 #28
0
static handler_t mod_authn_gssapi_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw)
{
    krb5_context kcontext  = NULL;
    krb5_keytab keytab     = NULL;
    krb5_principal s_princ = NULL;
    krb5_principal c_princ = NULL;
    krb5_creds c_creds;
    krb5_ccache c_ccache   = NULL;
    krb5_ccache ret_ccache = NULL;
    krb5_error_code code;
    int ret;
    buffer *sprinc;
    buffer *user_at_realm  = NULL;
    plugin_data * const p = (plugin_data *)p_d;

    if (*pw == '\0') {
        log_error_write(srv, __FILE__, __LINE__, "s", "Empty passwords are not accepted");
        return mod_authn_gssapi_send_401_unauthorized_basic(srv, con);
    }

    mod_authn_gssapi_patch_connection(srv, con, p);

    code = krb5_init_context(&kcontext);
    if (code) {
        log_error_write(srv, __FILE__, __LINE__, "sd", "krb5_init_context():", code);
        return mod_authn_gssapi_send_401_unauthorized_basic(srv, con); /*(well, should be 500)*/
    }

    code = krb5_kt_resolve(kcontext, p->conf.auth_gssapi_keytab->ptr, &keytab);
    if (code) {
        log_error_write(srv, __FILE__, __LINE__, "sdb", "krb5_kt_resolve():", code, p->conf.auth_gssapi_keytab);
        return mod_authn_gssapi_send_401_unauthorized_basic(srv, con); /*(well, should be 500)*/
    }

    sprinc = buffer_init_buffer(p->conf.auth_gssapi_principal);
    if (strchr(sprinc->ptr, '/') == NULL) {
        /*(copy HTTP Host, omitting port if port is present)*/
        /* ??? Should con->server_name be used if http_host not present?
         * ??? What if con->server_name is not set?
         * ??? Will this work below if IPv6 provided in Host?  probably not */
        if (!buffer_is_empty(con->request.http_host)) {
            buffer_append_string(sprinc, "/");
            buffer_append_string_len(sprinc, con->request.http_host->ptr, strcspn(con->request.http_host->ptr, ":"));
        }
    }

    /*(init c_creds before anything which might krb5_free_cred_contents())*/
    memset(&c_creds, 0, sizeof(c_creds));

    ret = krb5_parse_name(kcontext, sprinc->ptr, &s_princ);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_parse_name", sprinc->ptr, kcontext, ret);
        ret = -1;
        goto end;
    }

    if (strchr(username->ptr, '@') == NULL) {
        user_at_realm = buffer_init_buffer(username);
        BUFFER_APPEND_STRING_CONST(user_at_realm, "@");
        buffer_append_string_buffer(user_at_realm, require->realm);
    }

    ret = krb5_parse_name(kcontext, (user_at_realm ? user_at_realm->ptr : username->ptr), &c_princ);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_parse_name", (user_at_realm ? user_at_realm->ptr : username->ptr), kcontext, ret);
        if (user_at_realm) buffer_free(user_at_realm);
        ret = -1;
        goto end;
    }
    if (user_at_realm) buffer_free(user_at_realm);
    /* XXX: if the qualified username with @realm should be in REMOTE_USER,
     * then http_auth_backend_t basic interface needs to change to pass
     * modifiable buffer *username, but note that const char *pw follows
     * in the truncated buffer *username, so pw would need to be copied
     * before modifying buffer *username */

    /*
     * char *name = NULL;
     * ret = krb5_unparse_name(kcontext, c_princ, &name);
     * if (ret == 0) {
     *    log_error_write(srv, __FILE__, __LINE__, "sbss", "Trying to get TGT for user:"******"password:"******"krb5_get_init_creds_password", NULL, kcontext, ret);
        goto end;
    }

    ret = mod_authn_gssapi_verify_krb5_init_creds(srv, kcontext, &c_creds, s_princ, keytab);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "mod_authn_gssapi_verify_krb5_init_creds", NULL, kcontext, ret);
        goto end;
    }

    ret = krb5_cc_resolve(kcontext, "MEMORY:", &ret_ccache);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_cc_resolve", NULL, kcontext, ret);
        goto end;
    }

    ret = krb5_cc_initialize(kcontext, ret_ccache, c_princ);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_cc_initialize", NULL, kcontext, ret);
        goto end;
    }

    ret = krb5_cc_store_cred(kcontext, ret_ccache, &c_creds);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_cc_store_cred", NULL, kcontext, ret);
        goto end;
    }

    c_ccache = ret_ccache;
    ret_ccache = NULL;

    end:

        krb5_free_cred_contents(kcontext, &c_creds);
        if (ret_ccache)
            krb5_cc_destroy(kcontext, ret_ccache);

        if (!ret && c_ccache && (ret = mod_authn_gssapi_store_krb5_creds(srv, con, p, kcontext, c_ccache))) {
            log_error_write(srv, __FILE__, __LINE__, "sb", "mod_authn_gssapi_store_krb5_creds failed for", username);
        }

        buffer_free(sprinc);
        if (c_princ)
            krb5_free_principal(kcontext, c_princ);
        if (s_princ)
            krb5_free_principal(kcontext, s_princ);
        if (c_ccache)
            krb5_cc_destroy(kcontext, c_ccache);
        if (keytab)
            krb5_kt_close(kcontext, keytab);

        krb5_free_context(kcontext);

        if (0 == ret && http_auth_match_rules(require,username->ptr,NULL,NULL)){
            return HANDLER_GO_ON;
        }
        else {
            /* ret == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN or no authz rules match */
            log_error_write(srv, __FILE__, __LINE__, "sbsBsB", "password doesn't match for", con->uri.path, "username:"******", IP:", con->dst_addr_buf);
            return mod_authn_gssapi_send_401_unauthorized_basic(srv, con);
        }
}
コード例 #29
0
ファイル: verify_user_kerberos.c プロジェクト: 340211173/xrdp
/* returns boolean */
static int
k5_kinit(struct k_opts *opts, struct k5_data *k5, struct user_info *u_info)
{
    char *doing;
    int notix = 1;
    krb5_keytab keytab = 0;
    krb5_creds my_creds;
    krb5_error_code code = 0;
    krb5_get_init_creds_opt options;
    krb5_address **addresses;

    krb5_get_init_creds_opt_init(&options);
    g_memset(&my_creds, 0, sizeof(my_creds));

    /*
      From this point on, we can goto cleanup because my_creds is
      initialized.
    */
    if (opts->lifetime)
    {
        krb5_get_init_creds_opt_set_tkt_life(&options, opts->lifetime);
    }

    if (opts->rlife)
    {
        krb5_get_init_creds_opt_set_renew_life(&options, opts->rlife);
    }

    if (opts->forwardable)
    {
        krb5_get_init_creds_opt_set_forwardable(&options, 1);
    }

    if (opts->not_forwardable)
    {
        krb5_get_init_creds_opt_set_forwardable(&options, 0);
    }

    if (opts->proxiable)
    {
        krb5_get_init_creds_opt_set_proxiable(&options, 1);
    }

    if (opts->not_proxiable)
    {
        krb5_get_init_creds_opt_set_proxiable(&options, 0);
    }

    if (opts->addresses)
    {
        addresses = NULL;
        code = krb5_os_localaddr(k5->ctx, &addresses);

        if (code != 0)
        {
            g_printf("krb5_os_localaddr failed in k5_kinit\n");
            goto cleanup;
        }

        krb5_get_init_creds_opt_set_address_list(&options, addresses);
    }

    if (opts->no_addresses)
    {
        krb5_get_init_creds_opt_set_address_list(&options, NULL);
    }

    if ((opts->action == INIT_KT) && opts->keytab_name)
    {
        code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab);

        if (code != 0)
        {
            g_printf("krb5_kt_resolve failed in k5_kinit\n");
            goto cleanup;
        }
    }

    switch (opts->action)
    {
        case INIT_PW:
            code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me,
                                                0, kinit_prompter, u_info,
                                                opts->starttime,
                                                opts->service_name,
                                                &options);
            break;
        case INIT_KT:
            code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me,
                                              keytab,
                                              opts->starttime,
                                              opts->service_name,
                                              &options);
            break;
        case VALIDATE:
            code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->cc,
                                            opts->service_name);
            break;
        case RENEW:
            code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->cc,
                                          opts->service_name);
            break;
    }

    if (code != 0)
    {
        doing = 0;

        switch (opts->action)
        {
            case INIT_PW:
            case INIT_KT:
                doing = "getting initial credentials";
                break;
            case VALIDATE:
                doing = "validating credentials";
                break;
            case RENEW:
                doing = "renewing credentials";
                break;
        }

        if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
        {
            g_printf("sesman: Password incorrect while %s in k5_kinit\n", doing);
        }
        else
        {
            g_printf("sesman: error while %s in k5_kinit\n", doing);
        }

        goto cleanup;
    }

    if (!opts->lifetime)
    {
        /* We need to figure out what lifetime to use for Kerberos 4. */
        opts->lifetime = my_creds.times.endtime - my_creds.times.authtime;
    }

    code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me);

    if (code != 0)
    {
        g_printf("krb5_cc_initialize failed in k5_kinit\n");
        goto cleanup;
    }

    code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds);

    if (code != 0)
    {
        g_printf("krb5_cc_store_cred failed in k5_kinit\n");
        goto cleanup;
    }

    notix = 0;

cleanup:

    if (my_creds.client == k5->me)
    {
        my_creds.client = 0;
    }

    krb5_free_cred_contents(k5->ctx, &my_creds);

    if (keytab)
    {
        krb5_kt_close(k5->ctx, keytab);
    }

    return notix ? 0 : 1;
}
コード例 #30
0
ファイル: akimpersonate.c プロジェクト: adeason/openafs
/*
 * Print a krb5 ticket in our service key, for the supplied client principal.
 * The path to a keytab is mandatory, but the service principal may be
 * guessed from the keytab contents if desired.  The keytab entry must be
 * one of the allowed_enctypes (a zero-terminated list) if a non-NULL
 * parameter is passed.
 */
krb5_error_code
get_credv5_akimpersonate(krb5_context context, char* keytab,
			 krb5_principal service_principal,
			 krb5_principal client_principal, time_t starttime,
			 time_t endtime, const int *allowed_enctypes,
			 krb5_creds** out_creds /* out */ )
{
    char *tmpkt = NULL;
    struct stat tstat;
    char *ktname = NULL;
    krb5_error_code code;
    krb5_keytab kt = 0;
    krb5_keytab_entry entry[1];
    krb5_creds *creds = 0;
    krb5_enctype enctype;
    krb5_keyblock session_key[1];
#if USING_HEIMDAL
    Ticket *ticket_reply;
    EncTicketPart *enc_tkt_reply;
#else
    krb5_ticket *ticket_reply;
    krb5_enc_tkt_part *enc_tkt_reply;
#endif
    *out_creds = NULL;
    enctype = 0; /* AKIMPERSONATE_IGNORE_ENCTYPE */
    memset(entry, 0, sizeof *entry);
    memset(session_key, 0, sizeof *session_key);
    ticket_reply = NULL;
    enc_tkt_reply = NULL;

    creds = calloc(1, sizeof(*creds));
    if (creds == NULL) {
        code = ENOMEM;
        goto cleanup;
    }
    code = alloc_ticket(&ticket_reply);
    if (code != 0)
	goto cleanup;
    code = alloc_enc_tkt_part(&enc_tkt_reply);
    if (code != 0)
	goto cleanup;
    /* Empty list of allowed etypes must fail.  Do it here to avoid issues. */
    if (allowed_enctypes != NULL && *allowed_enctypes == 0) {
	code = KRB5_BAD_ENCTYPE;
	goto cleanup;
    }
    if (allowed_enctypes == NULL)
        allowed_enctypes = any_enctype;

    if (keytab != NULL) {
	tmpkt = strdup(keytab);
	if (!tmpkt)
	    code = ENOMEM;
    } else {
	tmpkt = malloc(256);
	if (!tmpkt)
	    code = ENOMEM;
	else
	    code = krb5_kt_default_name(context, tmpkt, 256);
    }
    if (code)
	goto cleanup;

    if (strncmp(tmpkt, "WRFILE:", 7) == 0)
	ktname = &(tmpkt[7]);
    else if (strncmp(tmpkt, "FILE:", 5) == 0)
	ktname = &(tmpkt[5]);

    if (ktname && (stat(ktname, &tstat) != 0)) {
	code = KRB5_KT_NOTFOUND;
	goto cleanup;
    }

    code = krb5_kt_resolve(context, tmpkt, &kt);
    if (code != 0)
        goto cleanup;

    code = pick_enctype_and_principal(context, kt, allowed_enctypes,
				      &enctype, &service_principal, entry);
    if (code != 0)
	goto cleanup;

    /* Conjure up a random session key */
    deref_keyblock_enctype(session_key) = enctype;
#if USING_HEIMDAL
    code = krb5_generate_random_keyblock(context, enctype, session_key);
#else
    code = krb5_c_make_random_key(context, enctype, session_key);
#endif
    if (code != 0)
        goto cleanup;

    populate_enc_tkt(session_key, client_principal, starttime, endtime,
		     enc_tkt_reply);

    code = encrypt_enc_tkt(context, service_principal, entry, ticket_reply,
			   enc_tkt_reply);
    if (code != 0)
	goto cleanup;

    code = populate_creds(context, service_principal, client_principal,
			  session_key, ticket_reply, enc_tkt_reply, creds);
    if (code != 0)
	goto cleanup;

    /* return creds */
    *out_creds = creds;
    creds = NULL;
cleanup:
    if (tmpkt)
	free(tmpkt);
    if (deref_enc_data(&ticket_reply->enc_part) != NULL)
        free(deref_enc_data(&ticket_reply->enc_part));
    krb5_free_keytab_entry_contents(context, entry);
    if (client_principal != NULL)
        krb5_free_principal(context, client_principal);
    if (service_principal != NULL)
        krb5_free_principal(context, service_principal);
    if (kt != NULL)
        krb5_kt_close(context, kt);
    if (creds != NULL)
	krb5_free_creds(context, creds);
    krb5_free_keyblock_contents(context, session_key);
    free_ticket(ticket_reply);
    free_enc_tkt_part(enc_tkt_reply);
    return code;
}