示例#1
0
static gss_client_response *create_krb5_ccache(gss_server_state *state, krb5_context kcontext, krb5_principal princ, krb5_ccache *ccache)
{
    char *ccname = NULL;
    int fd;
    krb5_error_code problem;
    krb5_ccache tmp_ccache = NULL;
    gss_client_response *error = NULL;

    // TODO: mod_auth_kerb used a temp file under /run/httpd/krbcache. what can we do?
    ccname = strdup("FILE:/tmp/krb5cc_nodekerberos_XXXXXX");
    if (!ccname) die1("Memory allocation failed");

    fd = mkstemp(ccname + strlen("FILE:"));
    if (fd < 0) {
	error = other_error("mkstemp() failed: %s", strerror(errno));
	goto end;
    }

    close(fd);

    problem = krb5_cc_resolve(kcontext, ccname, &tmp_ccache);
    if (problem) {
       error = krb5_ctx_error(kcontext, problem);
       goto end;
    }

    problem = krb5_cc_initialize(kcontext, tmp_ccache, princ);
    if (problem) {
	error = krb5_ctx_error(kcontext, problem);
	goto end;
    }

    state->delegated_credentials_cache = strdup(ccname);

    // TODO: how/when to cleanup the creds cache file?
    // TODO: how to expose the credentials expiration time?

    *ccache = tmp_ccache;
    tmp_ccache = NULL;

 end:
    if (tmp_ccache)
	krb5_cc_destroy(kcontext, tmp_ccache);

    if (ccname && error)
	unlink(ccname);

    if (ccname)
	free(ccname);

    return error;
}
示例#2
0
static gss_client_response *store_gss_creds(gss_server_state *state)
{
    OM_uint32 maj_stat, min_stat;
    krb5_principal princ = NULL;
    krb5_ccache ccache = NULL;
    krb5_error_code problem;
    krb5_context context;
    gss_client_response *response = NULL;

    problem = krb5_init_context(&context);
    if (problem) {
	response = other_error("No auth_data value in request from client");
        return response;
    }

    problem = krb5_parse_name(context, state->username, &princ);
    if (problem) {
	response = krb5_ctx_error(context, problem);
	goto end;
    }

    if ((response = create_krb5_ccache(state, context, princ, &ccache)))
    {
	goto end;
    }

    maj_stat = gss_krb5_copy_ccache(&min_stat, state->client_creds, ccache);
    if (GSS_ERROR(maj_stat)) {
        response = gss_error(__func__, "gss_krb5_copy_ccache", maj_stat, min_stat);
        response->return_code = AUTH_GSS_ERROR;
        goto end;
    }

    krb5_cc_close(context, ccache);
    ccache = NULL;

    response = calloc(1, sizeof(gss_client_response));
    if(response == NULL) die1("Memory allocation failed");
    // TODO: something other than AUTH_GSS_COMPLETE?
    response->return_code = AUTH_GSS_COMPLETE;

 end:
    if (princ)
	krb5_free_principal(context, princ);
    if (ccache)
	krb5_cc_destroy(context, ccache);
    krb5_free_context(context);

    return response;
}
示例#3
0
	void simple_socket_stoppable::wait_for_read () {
		if (fd_to_monitor == INVALID_SOCKET) return;
		fd_set select_fds;
		FD_ZERO(&select_fds);
		FD_SET(sock, &select_fds);
		FD_SET(fd_to_monitor, &select_fds);
		timeval timeout_copy = *timeout; // For Linux
		timeval* select_tm = (timeout_action == timeout_act::NO_TIMEOUT) ? NULL : &timeout_copy;
		int selcode = select(((fd_to_monitor > sock) ? fd_to_monitor : sock), &select_fds, NULL, NULL, select_tm);
		if (selcode == SOCKET_ERROR) throw other_error("select() error in stoppable socket");
		if (selcode) {
			if (FD_ISSET(sock, &select_fds)) return;
			else throw stop_exception(context, fd_to_monitor);
		} else {
			if (timeout_action == timeout_act::RAISE_STOP) throw stop_exception(context, fd_to_monitor);
			else throw io_error(io_error::READ);
		}
	}
示例#4
0
static gss_client_response *init_gss_creds(const char *credential_cache, gss_cred_id_t *cred) {
  OM_uint32 maj_stat;
  OM_uint32 min_stat;
  krb5_context context;
  krb5_error_code problem;
  gss_client_response *response = NULL;
  krb5_ccache ccache = NULL;

  *cred = GSS_C_NO_CREDENTIAL;

  if (credential_cache == NULL || strlen(credential_cache) == 0) {
      return NULL;
  }

  problem = krb5_init_context(&context);
  if (problem) {
      return other_error("unable to initialize krb5 context (%d)", (int)problem);
  }

  problem = krb5_cc_resolve(context, credential_cache, &ccache);
  if (problem) {
      response = krb5_ctx_error(context, problem);
      goto done;
  }

  maj_stat = gss_krb5_import_cred(&min_stat, ccache, NULL, NULL, cred);
  if (GSS_ERROR(maj_stat)) {
    response = gss_error(__func__, "gss_krb5_import_cred", maj_stat, min_stat);
    response->return_code = AUTH_GSS_ERROR;
  }

 done:
  if (response && ccache) {
      krb5_cc_close(context, ccache);
  }

  krb5_free_context(context);

  return response;
}
 static other_error create(int id_, const std::string& what_arg)
 {
     std::string w = exception::name("other_error", id_) + what_arg;
     return other_error(id_, w.c_str());
 }
示例#6
0
/*
 * username, password: Credentials to validate. Null not allowed
 * service: Service principal (e.g. HTTP/somehost.example.org) of key
 *          stored in default keytab which will be used to verify KDC.
 *          Empty string (*not* NULL) will bypass KDC verification
 * return: response->return_code will be
 * 		-1 (AUTH_GSS_ERROR) for error, see response->message
 * 	 	0 for auth fail
 * 	 	1 for auth ok
 */
gss_client_response *authenticate_user_krb5_password(const char *username,
							 const char *password,
							 const char *service)
{
    krb5_context context = NULL;
    krb5_error_code problem;
    krb5_principal user_principal = NULL;
    krb5_get_init_creds_opt *opt = NULL;
    krb5_creds creds;
    bool auth_ok = false;

    gss_client_response *response = NULL;

    if (username == NULL || password == NULL || service == NULL) {
	return other_error("username, password and service must all be non-null");
    }

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

    problem = krb5_init_context(&context);
    if (problem) {
	// can't call krb5_ctx_error without a context...
	response = other_error("unable to initialize krb5 context (%d)", (int)problem);
	goto out;
    }

    problem = krb5_parse_name(context, username, &user_principal);
    if (problem) {
	response = krb5_ctx_error(context, problem);
	goto out;
    }

    problem = krb5_get_init_creds_opt_alloc(context, &opt);
    if (problem) {
	response = krb5_ctx_error(context, problem);
        goto out;
    }

    problem = krb5_get_init_creds_password(context, &creds, user_principal,
                                          (char *)password, NULL,
					  NULL, 0, NULL, opt);

    switch (problem) {
    case 0:
        auth_ok = true;
        break;
    case KRB5KDC_ERR_PREAUTH_FAILED:
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
        /* "expected" error */
        auth_ok = false;
        break;
    default:
	/* unexpected error */
	response = krb5_ctx_error(context, problem);
	break;
    }

    if (auth_ok && strlen(service) > 0) {
	response = verify_krb5_kdc(context, &creds, service);
    }

  out:
    krb5_free_cred_contents(context, &creds);

    if (opt != NULL) {
	krb5_get_init_creds_opt_free(context, opt);
    }

    if (user_principal != NULL) {
	krb5_free_principal(context, user_principal);
    }

    if (context != NULL) {
	krb5_free_context(context);
    }

    if (response == NULL) {
	response = calloc(1, sizeof(gss_client_response));
	if(response == NULL) die1("Memory allocation failed");
	response->return_code = auth_ok ? 1 : 0;
    }

    return response;
}