static int pg_krb5_init(PQExpBuffer errorMessage, struct krb5_info * info) { krb5_error_code retval; if (info->pg_krb5_initialised) return STATUS_OK; retval = krb5_init_context(&(info->pg_krb5_context)); if (retval) { printfPQExpBuffer(errorMessage, "pg_krb5_init: krb5_init_context: %s\n", error_message(retval)); return STATUS_ERROR; } retval = krb5_cc_default(info->pg_krb5_context, &(info->pg_krb5_ccache)); if (retval) { printfPQExpBuffer(errorMessage, "pg_krb5_init: krb5_cc_default: %s\n", error_message(retval)); krb5_free_context(info->pg_krb5_context); return STATUS_ERROR; } retval = krb5_cc_get_principal(info->pg_krb5_context, info->pg_krb5_ccache, &(info->pg_krb5_client)); if (retval) { printfPQExpBuffer(errorMessage, "pg_krb5_init: krb5_cc_get_principal: %s\n", error_message(retval)); krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache); krb5_free_context(info->pg_krb5_context); return STATUS_ERROR; } retval = krb5_unparse_name(info->pg_krb5_context, info->pg_krb5_client, &(info->pg_krb5_name)); if (retval) { printfPQExpBuffer(errorMessage, "pg_krb5_init: krb5_unparse_name: %s\n", error_message(retval)); krb5_free_principal(info->pg_krb5_context, info->pg_krb5_client); krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache); krb5_free_context(info->pg_krb5_context); return STATUS_ERROR; } info->pg_krb5_name = pg_an_to_ln(info->pg_krb5_name); info->pg_krb5_initialised = 1; return STATUS_OK; }
static int pg_krb5_init(char *PQerrormsg) { krb5_error_code retval; if (pg_krb5_initialised) return STATUS_OK; retval = krb5_init_context(&pg_krb5_context); if (retval) { snprintf(PQerrormsg, PQERRORMSG_LENGTH, "pg_krb5_init: krb5_init_context: %s\n", error_message(retval)); return STATUS_ERROR; } retval = krb5_cc_default(pg_krb5_context, &pg_krb5_ccache); if (retval) { snprintf(PQerrormsg, PQERRORMSG_LENGTH, "pg_krb5_init: krb5_cc_default: %s\n", error_message(retval)); krb5_free_context(pg_krb5_context); return STATUS_ERROR; } retval = krb5_cc_get_principal(pg_krb5_context, pg_krb5_ccache, &pg_krb5_client); if (retval) { snprintf(PQerrormsg, PQERRORMSG_LENGTH, "pg_krb5_init: krb5_cc_get_principal: %s\n", error_message(retval)); krb5_cc_close(pg_krb5_context, pg_krb5_ccache); krb5_free_context(pg_krb5_context); return STATUS_ERROR; } retval = krb5_unparse_name(pg_krb5_context, pg_krb5_client, &pg_krb5_name); if (retval) { snprintf(PQerrormsg, PQERRORMSG_LENGTH, "pg_krb5_init: krb5_unparse_name: %s\n", error_message(retval)); krb5_free_principal(pg_krb5_context, pg_krb5_client); krb5_cc_close(pg_krb5_context, pg_krb5_ccache); krb5_free_context(pg_krb5_context); return STATUS_ERROR; } pg_krb5_name = pg_an_to_ln(pg_krb5_name); pg_krb5_initialised = 1; return STATUS_OK; }
/* * pg_krb5_recvauth -- server routine to receive authentication information * from the client * * We still need to compare the username obtained from the client's setup * packet to the authenticated name, as described in pg_krb4_recvauth. This * is a bit more problematic in v5, as described above in pg_an_to_ln. * * We have our own keytab file because postgres is unlikely to run as root, * and so cannot read the default keytab. */ static int pg_krb5_recvauth(Port *port) { krb5_error_code retval; int ret; krb5_auth_context auth_context = NULL; krb5_ticket *ticket; char *kusername; ret = pg_krb5_init(); if (ret != STATUS_OK) return ret; retval = krb5_recvauth(pg_krb5_context, &auth_context, (krb5_pointer) & port->sock, PG_KRB_SRVNAM, pg_krb5_server, 0, pg_krb5_keytab, &ticket); if (retval) { ereport(LOG, (errmsg("Kerberos recvauth returned error %d", retval))); com_err("postgres", retval, "from krb5_recvauth"); return STATUS_ERROR; } /* * The "client" structure comes out of the ticket and is therefore * authenticated. Use it to check the username obtained from the * postmaster startup packet. * * I have no idea why this is considered necessary. */ #if defined(HAVE_KRB5_TICKET_ENC_PART2) retval = krb5_unparse_name(pg_krb5_context, ticket->enc_part2->client, &kusername); #elif defined(HAVE_KRB5_TICKET_CLIENT) retval = krb5_unparse_name(pg_krb5_context, ticket->client, &kusername); #else #error "bogus configuration" #endif if (retval) { ereport(LOG, (errmsg("Kerberos unparse_name returned error %d", retval))); com_err("postgres", retval, "while unparsing client name"); krb5_free_ticket(pg_krb5_context, ticket); krb5_auth_con_free(pg_krb5_context, auth_context); return STATUS_ERROR; } kusername = pg_an_to_ln(kusername); if (strncmp(port->user_name, kusername, SM_DATABASE_USER)) { ereport(LOG, (errmsg("unexpected Kerberos user name received from client (received \"%s\", expected \"%s\")", port->user_name, kusername))); ret = STATUS_ERROR; } else ret = STATUS_OK; krb5_free_ticket(pg_krb5_context, ticket); krb5_auth_con_free(pg_krb5_context, auth_context); free(kusername); return ret; }