/* * fe_getauthname -- returns a pointer to dynamic space containing whatever * name the user has authenticated to the system * if there is an error, return the error message in PQerrormsg */ char * fe_getauthname(char *PQerrormsg) { const char *name = NULL; char *authn; MsgType authsvc; #ifdef WIN32 char username[128]; DWORD namesize = sizeof(username) - 1; #else char pwdbuf[BUFSIZ]; struct passwd pwdstr; struct passwd *pw = NULL; #endif authsvc = fe_getauthsvc(PQerrormsg); /* this just guards against broken DEFAULT_CLIENT_AUTHSVC, see above */ if (authsvc == 0) return NULL; /* leave original error message in place */ pglock_thread(); #ifdef KRB4 if (authsvc == STARTUP_KRB4_MSG) name = pg_krb4_authname(PQerrormsg); #endif #ifdef KRB5 if (authsvc == STARTUP_KRB5_MSG) name = pg_krb5_authname(PQerrormsg); #endif if (authsvc == STARTUP_MSG || (authsvc == STARTUP_KRB4_MSG && !name) || (authsvc == STARTUP_KRB5_MSG && !name)) { #ifdef WIN32 if (GetUserName(username, &namesize)) name = username; #else if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pw) == 0) name = pw->pw_name; #endif } if (authsvc != STARTUP_MSG && authsvc != STARTUP_KRB4_MSG && authsvc != STARTUP_KRB5_MSG) snprintf(PQerrormsg, PQERRORMSG_LENGTH, libpq_gettext("fe_getauthname: invalid authentication system: %d\n"), authsvc); authn = name ? strdup(name) : NULL; pgunlock_thread(); return authn; }
/* * pg_fe_getauthname * * Returns a pointer to dynamic space containing whatever name the user * has authenticated to the system. If there is an error, return NULL. */ char * pg_fe_getauthname(void) { const char *name = NULL; char *authn; #ifdef WIN32 char username[128]; DWORD namesize = sizeof(username) - 1; #else char pwdbuf[BUFSIZ]; struct passwd pwdstr; struct passwd *pw = NULL; #endif /* * Some users are using configure --enable-thread-safety-force, so we * might as well do the locking within our library to protect * pqGetpwuid(). In fact, application developers can use getpwuid() in * their application if they use the locking call we provide, or install * their own locking function using PQregisterThreadLock(). */ pglock_thread(); /* * We document PQconndefaults() to return NULL for a memory allocation * failure. We don't have an API to return a user name lookup failure, so * we just assume it always succeeds. */ #ifdef WIN32 if (GetUserName(username, &namesize)) name = username; #else if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pw) == 0) name = pw->pw_name; #endif authn = name ? strdup(name) : NULL; pgunlock_thread(); return authn; }
/* * pg_fe_getauthname -- returns a pointer to dynamic space containing whatever * name the user has authenticated to the system * * if there is an error, return NULL with an error message in errorMessage */ char * pg_fe_getauthname(PQExpBuffer errorMessage) { const char *name = NULL; char *authn; #ifdef WIN32 char username[128]; DWORD namesize = sizeof(username) - 1; #else char pwdbuf[BUFSIZ]; struct passwd pwdstr; struct passwd *pw = NULL; #endif /* * Some users are using configure --enable-thread-safety-force, so we * might as well do the locking within our library to protect * pqGetpwuid(). In fact, application developers can use getpwuid() in * their application if they use the locking call we provide, or install * their own locking function using PQregisterThreadLock(). */ pglock_thread(); if (!name) { #ifdef WIN32 if (GetUserName(username, &namesize)) name = username; #else if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pw) == 0) name = pw->pw_name; #endif } authn = name ? strdup(name) : NULL; pgunlock_thread(); return authn; }
/* * pg_fe_sendauth * client demux routine for outgoing authentication information */ int pg_fe_sendauth(AuthRequest areq, PGconn *conn) { switch (areq) { case AUTH_REQ_OK: break; case AUTH_REQ_KRB4: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Kerberos 4 authentication not supported\n")); return STATUS_ERROR; case AUTH_REQ_KRB5: #ifdef KRB5 pglock_thread(); if (pg_krb5_sendauth(conn) != STATUS_OK) { /* Error message already filled in */ pgunlock_thread(); return STATUS_ERROR; } pgunlock_thread(); break; #else printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Kerberos 5 authentication not supported\n")); return STATUS_ERROR; #endif #if defined(ENABLE_GSS) || defined(ENABLE_SSPI) case AUTH_REQ_GSS: { int r; pglock_thread(); /* * If we have both GSS and SSPI support compiled in, use SSPI * support by default. This is overridable by a connection * string parameter. Note that when using SSPI we still leave * the negotiate parameter off, since we want SSPI to use the * GSSAPI kerberos protocol. For actual SSPI negotiate * protocol, we use AUTH_REQ_SSPI. */ #if defined(ENABLE_GSS) && defined(ENABLE_SSPI) if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0)) r = pg_GSS_startup(conn); else r = pg_SSPI_startup(conn, 0); #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI) r = pg_GSS_startup(conn); #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI) r = pg_SSPI_startup(conn, 0); #endif if (r != STATUS_OK) { /* Error message already filled in. */ pgunlock_thread(); return STATUS_ERROR; } pgunlock_thread(); } break; case AUTH_REQ_GSS_CONT: { int r; pglock_thread(); #if defined(ENABLE_GSS) && defined(ENABLE_SSPI) if (conn->usesspi) r = pg_SSPI_continue(conn); else r = pg_GSS_continue(conn); #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI) r = pg_GSS_continue(conn); #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI) r = pg_SSPI_continue(conn); #endif if (r != STATUS_OK) { /* Error message already filled in. */ pgunlock_thread(); return STATUS_ERROR; } pgunlock_thread(); } break; #else case AUTH_REQ_GSS: case AUTH_REQ_GSS_CONT: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("GSSAPI authentication not supported\n")); return STATUS_ERROR; #endif #ifdef ENABLE_SSPI case AUTH_REQ_SSPI: /* * SSPI has it's own startup message so libpq can decide which * method to use. Indicate to pg_SSPI_startup that we want SSPI * negotiation instead of Kerberos. */ pglock_thread(); if (pg_SSPI_startup(conn, 1) != STATUS_OK) { /* Error message already filled in. */ pgunlock_thread(); return STATUS_ERROR; } pgunlock_thread(); break; #else case AUTH_REQ_SSPI: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("SSPI authentication not supported\n")); return STATUS_ERROR; #endif case AUTH_REQ_CRYPT: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Crypt authentication not supported\n")); return STATUS_ERROR; case AUTH_REQ_MD5: case AUTH_REQ_PASSWORD: conn->password_needed = true; if (conn->pgpass == NULL || conn->pgpass[0] == '\0') { printfPQExpBuffer(&conn->errorMessage, PQnoPasswordSupplied); return STATUS_ERROR; } if (pg_password_sendauth(conn, conn->pgpass, areq) != STATUS_OK) { printfPQExpBuffer(&conn->errorMessage, "fe_sendauth: error sending password authentication\n"); return STATUS_ERROR; } break; case AUTH_REQ_SCM_CREDS: if (pg_local_sendauth(conn) != STATUS_OK) return STATUS_ERROR; break; default: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("authentication method %u not supported\n"), areq); return STATUS_ERROR; } return STATUS_OK; }
/* * pg_fe_getauthname * * Returns a pointer to malloc'd space containing whatever name the user * has authenticated to the system. If there is an error, return NULL, * and put a suitable error message in *errorMessage if that's not NULL. */ char * pg_fe_getauthname(PQExpBuffer errorMessage) { char *result = NULL; const char *name = NULL; #ifdef WIN32 /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */ char username[256 + 1]; DWORD namesize = sizeof(username); #else uid_t user_id = geteuid(); char pwdbuf[BUFSIZ]; struct passwd pwdstr; struct passwd *pw = NULL; int pwerr; #endif /* * Some users are using configure --enable-thread-safety-force, so we * might as well do the locking within our library to protect * pqGetpwuid(). In fact, application developers can use getpwuid() in * their application if they use the locking call we provide, or install * their own locking function using PQregisterThreadLock(). */ pglock_thread(); #ifdef WIN32 if (GetUserName(username, &namesize)) name = username; else if (errorMessage) printfPQExpBuffer(errorMessage, libpq_gettext("user name lookup failure: error code %lu\n"), GetLastError()); #else pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw); if (pw != NULL) name = pw->pw_name; else if (errorMessage) { if (pwerr != 0) printfPQExpBuffer(errorMessage, libpq_gettext("could not look up local user ID %d: %s\n"), (int) user_id, pqStrerror(pwerr, pwdbuf, sizeof(pwdbuf))); else printfPQExpBuffer(errorMessage, libpq_gettext("local user with ID %d does not exist\n"), (int) user_id); } #endif if (name) { result = strdup(name); if (result == NULL && errorMessage) printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); } pgunlock_thread(); return result; }
/* * pg_fe_getauthname -- returns a pointer to dynamic space containing whatever * name the user has authenticated to the system * * if there is an error, return NULL with an error message in PQerrormsg */ char * pg_fe_getauthname(char *PQerrormsg) { #ifdef KRB5 const char *krb5_name = NULL; #endif const char *name = NULL; char *authn; #ifdef WIN32 char username[128]; DWORD namesize = sizeof(username) - 1; #else char pwdbuf[BUFSIZ]; struct passwd pwdstr; struct passwd *pw = NULL; #endif /* * pglock_thread() really only needs to be called around * pg_krb5_authname(), but some users are using configure * --enable-thread-safety-force, so we might as well do the locking within * our library to protect pqGetpwuid(). In fact, application developers * can use getpwuid() in their application if they use the locking call we * provide, or install their own locking function using * PQregisterThreadLock(). */ pglock_thread(); #ifdef KRB5 /* pg_krb5_authname gives us a strdup'd value that we need * to free later, however, we don't want to free 'name' directly * in case it's *not* a Kerberos login and we fall through to * name = pw->pw_name; */ krb5_name = pg_krb5_authname(PQerrormsg); name = krb5_name; #endif if (!name) { #ifdef WIN32 if (GetUserName(username, &namesize)) name = username; #else if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pw) == 0) name = pw->pw_name; #endif } authn = name ? strdup(name) : NULL; #ifdef KRB5 /* Free the strdup'd string from pg_krb5_authname, if we got one */ if (krb5_name) free(krb5_name); #endif pgunlock_thread(); return authn; }
/* * pg_fe_sendauth * client demux routine for outgoing authentication information */ int pg_fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname, const char *password, char *PQerrormsg) { #ifndef KRB5 (void) hostname; /* not used */ #endif switch (areq) { case AUTH_REQ_OK: break; case AUTH_REQ_KRB4: snprintf(PQerrormsg, PQERRORMSG_LENGTH, libpq_gettext("Kerberos 4 authentication not supported\n")); return STATUS_ERROR; case AUTH_REQ_KRB5: #ifdef KRB5 pglock_thread(); if (pg_krb5_sendauth(PQerrormsg, conn->sock, hostname, conn->krbsrvname) != STATUS_OK) { /* PQerrormsg already filled in */ pgunlock_thread(); return STATUS_ERROR; } pgunlock_thread(); break; #else snprintf(PQerrormsg, PQERRORMSG_LENGTH, libpq_gettext("Kerberos 5 authentication not supported\n")); return STATUS_ERROR; #endif case AUTH_REQ_MD5: case AUTH_REQ_CRYPT: case AUTH_REQ_PASSWORD: if (password == NULL || *password == '\0') { (void) snprintf(PQerrormsg, PQERRORMSG_LENGTH, PQnoPasswordSupplied); return STATUS_ERROR; } if (pg_password_sendauth(conn, password, areq) != STATUS_OK) { (void) snprintf(PQerrormsg, PQERRORMSG_LENGTH, "fe_sendauth: error sending password authentication\n"); return STATUS_ERROR; } break; case AUTH_REQ_SCM_CREDS: if (pg_local_sendauth(PQerrormsg, conn) != STATUS_OK) return STATUS_ERROR; break; default: snprintf(PQerrormsg, PQERRORMSG_LENGTH, libpq_gettext("authentication method %u not supported\n"), areq); return STATUS_ERROR; } return STATUS_OK; }
/* * pg_fe_sendauth * client demux routine for outgoing authentication information */ int pg_fe_sendauth(AuthRequest areq, PGconn *conn) { switch (areq) { case AUTH_REQ_OK: break; case AUTH_REQ_KRB4: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Kerberos 4 authentication not supported\n")); return STATUS_ERROR; case AUTH_REQ_KRB5: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Kerberos 5 authentication not supported\n")); return STATUS_ERROR; #if defined(ENABLE_GSS) || defined(ENABLE_SSPI) case AUTH_REQ_GSS: #if !defined(ENABLE_SSPI) /* no native SSPI, so use GSSAPI library for it */ case AUTH_REQ_SSPI: #endif { int r; pglock_thread(); /* * If we have both GSS and SSPI support compiled in, use SSPI * support by default. This is overridable by a connection * string parameter. Note that when using SSPI we still leave * the negotiate parameter off, since we want SSPI to use the * GSSAPI kerberos protocol. For actual SSPI negotiate * protocol, we use AUTH_REQ_SSPI. */ #if defined(ENABLE_GSS) && defined(ENABLE_SSPI) if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0)) r = pg_GSS_startup(conn); else r = pg_SSPI_startup(conn, 0); #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI) r = pg_GSS_startup(conn); #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI) r = pg_SSPI_startup(conn, 0); #endif if (r != STATUS_OK) { /* Error message already filled in. */ pgunlock_thread(); return STATUS_ERROR; } pgunlock_thread(); } break; case AUTH_REQ_GSS_CONT: { int r; pglock_thread(); #if defined(ENABLE_GSS) && defined(ENABLE_SSPI) if (conn->usesspi) r = pg_SSPI_continue(conn); else r = pg_GSS_continue(conn); #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI) r = pg_GSS_continue(conn); #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI) r = pg_SSPI_continue(conn); #endif if (r != STATUS_OK) { /* Error message already filled in. */ pgunlock_thread(); return STATUS_ERROR; } pgunlock_thread(); } break; #else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */ /* No GSSAPI *or* SSPI support */ case AUTH_REQ_GSS: case AUTH_REQ_GSS_CONT: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("GSSAPI authentication not supported\n")); return STATUS_ERROR; #endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */ #ifdef ENABLE_SSPI case AUTH_REQ_SSPI: /* * SSPI has it's own startup message so libpq can decide which * method to use. Indicate to pg_SSPI_startup that we want SSPI * negotiation instead of Kerberos. */ pglock_thread(); if (pg_SSPI_startup(conn, 1) != STATUS_OK) { /* Error message already filled in. */ pgunlock_thread(); return STATUS_ERROR; } pgunlock_thread(); break; #else /* * No SSPI support. However, if we have GSSAPI but not SSPI * support, AUTH_REQ_SSPI will have been handled in the codepath * for AUTH_REQ_GSSAPI above, so don't duplicate the case label in * that case. */ #if !defined(ENABLE_GSS) case AUTH_REQ_SSPI: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("SSPI authentication not supported\n")); return STATUS_ERROR; #endif /* !define(ENABLE_GSSAPI) */ #endif /* ENABLE_SSPI */ case AUTH_REQ_CRYPT: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("Crypt authentication not supported\n")); return STATUS_ERROR; case AUTH_REQ_MD5: case AUTH_REQ_PASSWORD: { char *password = conn->connhost[conn->whichhost].password; if (password == NULL) password = conn->pgpass; conn->password_needed = true; if (password == NULL || password[0] == '\0') { printfPQExpBuffer(&conn->errorMessage, PQnoPasswordSupplied); return STATUS_ERROR; } if (pg_password_sendauth(conn, password, areq) != STATUS_OK) { printfPQExpBuffer(&conn->errorMessage, "fe_sendauth: error sending password authentication\n"); return STATUS_ERROR; } break; } case AUTH_REQ_SCM_CREDS: if (pg_local_sendauth(conn) != STATUS_OK) return STATUS_ERROR; break; default: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("authentication method %u not supported\n"), areq); return STATUS_ERROR; } return STATUS_OK; }