/* * do frontend <-> pgpool authentication based on pool_hba.conf */ void ClientAuthentication(POOL_CONNECTION *frontend) { POOL_STATUS status = POOL_ERROR; if (! hba_getauthmethod(frontend)) { pool_error("missing or erroneous pool_hba.conf file"); pool_send_error_message(frontend, frontend->protoVersion, "XX000", "missing or erroneous pool_hba.conf file", "", "See pgpool log for details.", __FILE__, __LINE__); close_all_backend_connections(); /* * use exit(2) since this is not so fatal. other entries in * pool_hba.conf may be valid, so treat it as reject. */ child_exit(2); } switch (frontend->auth_method) { case uaReject: { /* * This could have come from an explicit "reject" entry in * pool_hba.conf, but more likely it means there was no matching * entry. Take pity on the poor user and issue a helpful * error message. NOTE: this is not a security breach, * because all the info reported here is known at the frontend * and must be assumed known to bad guys. We're merely helping * out the less clueful good guys. */ char hostinfo[NI_MAXHOST]; char *errmessage; int messagelen; getnameinfo_all(&frontend->raddr.addr, frontend->raddr.salen, hostinfo, sizeof(hostinfo), NULL, 0, NI_NUMERICHOST); messagelen = sizeof(hostinfo) + strlen(frontend->username) + strlen(frontend->database) + 80; if ((errmessage = (char *)malloc(messagelen+1)) == NULL) { pool_error("ClientAuthentication: malloc failed: %s", strerror(errno)); child_exit(1); } #ifdef USE_SSL snprintf(errmessage, messagelen+7, /* +7 is for "SSL off" */ "no pool_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s", hostinfo, frontend->username, frontend->database, frontend->ssl ? "SSL on" : "SSL off"); #else snprintf(errmessage, messagelen, "no pool_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"", hostinfo, frontend->username, frontend->database); #endif pool_error(errmessage); pool_send_error_message(frontend, frontend->protoVersion, "XX000", errmessage, "", "", __FILE__, __LINE__); free(errmessage); break; } /* case uaKrb4: */ /* break; */ /* case uaKrb5: */ /* break; */ /* case uaIdent: */ /* break; */ /* case uaMD5: */ /* break; */ /* case uaCrypt: */ /* break; */ /* case uaPassword: */ /* break; */ #ifdef USE_PAM case uaPAM: pam_frontend_kludge = frontend; status = CheckPAMAuth(frontend, frontend->username, ""); break; #endif /* USE_PAM */ case uaTrust: status = POOL_CONTINUE; break; } if (status == POOL_CONTINUE) sendAuthRequest(frontend, AUTH_REQ_OK); else if (status != POOL_CONTINUE) auth_failed(frontend); }
/* * Client authentication starts here. If there is an error, this * function does not return and the backend process is terminated. */ void ClientAuthentication(Port *port) { int status = STATUS_ERROR; /* * Get the authentication method to use for this frontend/database * combination. Note: a failure return indicates a problem with the * hba config file, not with the request. hba.c should have dropped * an error message into the postmaster logfile if it failed. */ if (hba_getauthmethod(port) != STATUS_OK) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("missing or erroneous pg_hba.conf file"), errhint("See server log for details."))); switch (port->auth_method) { case uaReject: /* * This could have come from an explicit "reject" entry in * pg_hba.conf, but more likely it means there was no matching * entry. Take pity on the poor user and issue a helpful * error message. NOTE: this is not a security breach, * because all the info reported here is known at the frontend * and must be assumed known to bad guys. We're merely helping * out the less clueful good guys. */ { char hostinfo[NI_MAXHOST]; getnameinfo_all(&port->raddr.addr, port->raddr.salen, hostinfo, sizeof(hostinfo), NULL, 0, NI_NUMERICHOST); #ifdef USE_SSL ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s", hostinfo, port->user_name, port->database_name, port->ssl ? gettext("SSL on") : gettext("SSL off")))); #else ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"", hostinfo, port->user_name, port->database_name))); #endif break; } case uaKrb4: /* Kerberos 4 only seems to work with AF_INET. */ if (port->raddr.addr.ss_family != AF_INET || port->laddr.addr.ss_family != AF_INET) ereport(FATAL, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Kerberos 4 only supports IPv4 connections"))); sendAuthRequest(port, AUTH_REQ_KRB4); status = pg_krb4_recvauth(port); break; case uaKrb5: sendAuthRequest(port, AUTH_REQ_KRB5); status = pg_krb5_recvauth(port); break; case uaIdent: /* * If we are doing ident on unix-domain sockets, use SCM_CREDS * only if it is defined and SO_PEERCRED isn't. */ #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \ (defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \ (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))) if (port->raddr.addr.ss_family == AF_UNIX) { #if defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED) /* * Receive credentials on next message receipt, BSD/OS, * NetBSD. We need to set this before the client sends the * next packet. */ int on = 1; if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0) ereport(FATAL, (errcode_for_socket_access(), errmsg("could not enable credential reception: %m"))); #endif sendAuthRequest(port, AUTH_REQ_SCM_CREDS); } #endif status = authident(port); break; case uaMD5: sendAuthRequest(port, AUTH_REQ_MD5); status = recv_and_check_password_packet(port); break; case uaCrypt: sendAuthRequest(port, AUTH_REQ_CRYPT); status = recv_and_check_password_packet(port); break; case uaPassword: sendAuthRequest(port, AUTH_REQ_PASSWORD); status = recv_and_check_password_packet(port); break; #ifdef USE_PAM case uaPAM: pam_port_cludge = port; status = CheckPAMAuth(port, port->user_name, ""); break; #endif /* USE_PAM */ case uaTrust: status = STATUS_OK; break; } if (status == STATUS_OK) sendAuthRequest(port, AUTH_REQ_OK); else auth_failed(port, status); }