/* * pg_krb5_authname -- returns a pointer to static space containing whatever * name the user has authenticated to the system */ static const char * pg_krb5_authname(char *PQerrormsg) { char *tmp_name; struct krb5_info info; info.pg_krb5_initialised = 0; if (pg_krb5_init(PQerrormsg, &info) != STATUS_OK) return NULL; tmp_name = strdup(info.pg_krb5_name); pg_krb5_destroy(&info); return tmp_name; }
/* * pg_krb5_sendauth -- client routine to send authentication information to * the server */ static int pg_krb5_sendauth(PGconn *conn) { krb5_error_code retval; int ret; krb5_principal server; krb5_auth_context auth_context = NULL; krb5_error *err_ret = NULL; struct krb5_info info; info.pg_krb5_initialised = 0; if (!(conn->pghost && conn->pghost[0] != '\0')) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("host name must be specified\n")); return STATUS_ERROR; } ret = pg_krb5_init(&conn->errorMessage, &info); if (ret != STATUS_OK) return ret; retval = krb5_sname_to_principal(info.pg_krb5_context, conn->pghost, conn->krbsrvname, KRB5_NT_SRV_HST, &server); if (retval) { printfPQExpBuffer(&conn->errorMessage, "pg_krb5_sendauth: krb5_sname_to_principal: %s\n", error_message(retval)); pg_krb5_destroy(&info); return STATUS_ERROR; } /* * libpq uses a non-blocking socket. But kerberos needs a blocking socket, * and we have to block somehow to do mutual authentication anyway. So we * temporarily make it blocking. */ if (!pg_set_block(conn->sock)) { char sebuf[256]; printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not set socket to blocking mode: %s\n"), pqStrerror(errno, sebuf, sizeof(sebuf))); krb5_free_principal(info.pg_krb5_context, server); pg_krb5_destroy(&info); return STATUS_ERROR; } retval = krb5_sendauth(info.pg_krb5_context, &auth_context, (krb5_pointer) & conn->sock, (char *) conn->krbsrvname, info.pg_krb5_client, server, AP_OPTS_MUTUAL_REQUIRED, NULL, 0, /* no creds, use ccache instead */ info.pg_krb5_ccache, &err_ret, NULL, NULL); if (retval) { if (retval == KRB5_SENDAUTH_REJECTED && err_ret) { #if defined(HAVE_KRB5_ERROR_TEXT_DATA) printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Kerberos 5 authentication rejected: %*s\n"), (int) err_ret->text.length, err_ret->text.data); #elif defined(HAVE_KRB5_ERROR_E_DATA) printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Kerberos 5 authentication rejected: %*s\n"), (int) err_ret->e_data->length, (const char *) err_ret->e_data->data); #else #error "bogus configuration" #endif } else { printfPQExpBuffer(&conn->errorMessage, "krb5_sendauth: %s\n", error_message(retval)); } if (err_ret) krb5_free_error(info.pg_krb5_context, err_ret); ret = STATUS_ERROR; } krb5_free_principal(info.pg_krb5_context, server); if (!pg_set_noblock(conn->sock)) { char sebuf[256]; printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not restore non-blocking mode on socket: %s\n"), pqStrerror(errno, sebuf, sizeof(sebuf))); ret = STATUS_ERROR; } pg_krb5_destroy(&info); return ret; }