00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include <sys/param.h>
00019 #include <sys/socket.h>
00020 #include <netinet/in.h>
00021 #include <arpa/inet.h>
00022 #include <unistd.h>
00023
00024 #include "libpq/auth.h"
00025 #include "libpq/crypt.h"
00026 #include "libpq/ip.h"
00027 #include "libpq/libpq.h"
00028 #include "libpq/pqformat.h"
00029 #include "libpq/md5.h"
00030 #include "miscadmin.h"
00031 #include "replication/walsender.h"
00032 #include "storage/ipc.h"
00033
00034
00035
00036
00037
00038
00039 static void sendAuthRequest(Port *port, AuthRequest areq);
00040 static void auth_failed(Port *port, int status);
00041 static char *recv_password_packet(Port *port);
00042 static int recv_and_check_password_packet(Port *port);
00043
00044
00045
00046
00047
00048
00049
00050 #define IDENT_USERNAME_MAX 512
00051
00052
00053 #define IDENT_PORT 113
00054
00055 static int ident_inet(hbaPort *port);
00056
00057 #ifdef HAVE_UNIX_SOCKETS
00058 static int auth_peer(hbaPort *port);
00059 #endif
00060
00061
00062
00063
00064
00065
00066 #ifdef USE_PAM
00067 #ifdef HAVE_PAM_PAM_APPL_H
00068 #include <pam/pam_appl.h>
00069 #endif
00070 #ifdef HAVE_SECURITY_PAM_APPL_H
00071 #include <security/pam_appl.h>
00072 #endif
00073
00074 #define PGSQL_PAM_SERVICE "postgresql"
00075
00076 static int CheckPAMAuth(Port *port, char *user, char *password);
00077 static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
00078 struct pam_response ** resp, void *appdata_ptr);
00079
00080 static struct pam_conv pam_passw_conv = {
00081 &pam_passwd_conv_proc,
00082 NULL
00083 };
00084
00085 static char *pam_passwd = NULL;
00086 static Port *pam_port_cludge;
00087
00088 #endif
00089
00090
00091
00092
00093
00094
00095 #ifdef USE_LDAP
00096 #ifndef WIN32
00097
00098 #define LDAP_DEPRECATED 1
00099 #include <ldap.h>
00100 #else
00101 #include <winldap.h>
00102
00103
00104 typedef
00105 ULONG (*__ldap_start_tls_sA) (
00106 IN PLDAP ExternalHandle,
00107 OUT PULONG ServerReturnValue,
00108 OUT LDAPMessage **result,
00109 IN PLDAPControlA * ServerControls,
00110 IN PLDAPControlA * ClientControls
00111 );
00112 #endif
00113
00114 static int CheckLDAPAuth(Port *port);
00115 #endif
00116
00117
00118
00119
00120
00121 #ifdef USE_SSL
00122 static int CheckCertAuth(Port *port);
00123 #endif
00124
00125
00126
00127
00128
00129
00130 char *pg_krb_server_keyfile;
00131 char *pg_krb_srvnam;
00132 bool pg_krb_caseins_users;
00133
00134
00135
00136
00137
00138
00139 #ifdef KRB5
00140 static int pg_krb5_recvauth(Port *port);
00141
00142 #include <krb5.h>
00143
00144 #if !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)
00145 #include <com_err.h>
00146 #endif
00147
00148
00149
00150
00151 static int pg_krb5_initialised;
00152 static krb5_context pg_krb5_context;
00153 static krb5_keytab pg_krb5_keytab;
00154 static krb5_principal pg_krb5_server;
00155 #endif
00156
00157
00158
00159
00160
00161
00162 #ifdef ENABLE_GSS
00163 #if defined(HAVE_GSSAPI_H)
00164 #include <gssapi.h>
00165 #else
00166 #include <gssapi/gssapi.h>
00167 #endif
00168
00169 static int pg_GSS_recvauth(Port *port);
00170 #endif
00171
00172
00173
00174
00175
00176
00177 #ifdef ENABLE_SSPI
00178 typedef SECURITY_STATUS
00179 (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (
00180 PCtxtHandle, void **);
00181 static int pg_SSPI_recvauth(Port *port);
00182 #endif
00183
00184
00185
00186
00187
00188 #ifdef USE_SSL
00189 #include <openssl/rand.h>
00190 #endif
00191 static int CheckRADIUSAuth(Port *port);
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 #define PG_MAX_AUTH_TOKEN_LENGTH 65535
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 ClientAuthentication_hook_type ClientAuthentication_hook = NULL;
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 static void
00235 auth_failed(Port *port, int status)
00236 {
00237 const char *errstr;
00238 int errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION;
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 if (status == STATUS_EOF)
00251 proc_exit(0);
00252
00253 switch (port->hba->auth_method)
00254 {
00255 case uaReject:
00256 case uaImplicitReject:
00257 errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
00258 break;
00259 case uaKrb5:
00260 errstr = gettext_noop("Kerberos 5 authentication failed for user \"%s\"");
00261 break;
00262 case uaTrust:
00263 errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
00264 break;
00265 case uaIdent:
00266 errstr = gettext_noop("Ident authentication failed for user \"%s\"");
00267 break;
00268 case uaPeer:
00269 errstr = gettext_noop("Peer authentication failed for user \"%s\"");
00270 break;
00271 case uaPassword:
00272 case uaMD5:
00273 errstr = gettext_noop("password authentication failed for user \"%s\"");
00274
00275 errcode_return = ERRCODE_INVALID_PASSWORD;
00276 break;
00277 case uaGSS:
00278 errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
00279 break;
00280 case uaSSPI:
00281 errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
00282 break;
00283 case uaPAM:
00284 errstr = gettext_noop("PAM authentication failed for user \"%s\"");
00285 break;
00286 case uaLDAP:
00287 errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
00288 break;
00289 case uaCert:
00290 errstr = gettext_noop("certificate authentication failed for user \"%s\"");
00291 break;
00292 case uaRADIUS:
00293 errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
00294 break;
00295 default:
00296 errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
00297 break;
00298 }
00299
00300 if (port->hba)
00301 ereport(FATAL,
00302 (errcode(errcode_return),
00303 errmsg(errstr, port->user_name),
00304 errdetail_log("Connection matched pg_hba.conf line %d: \"%s\"", port->hba->linenumber, port->hba->rawline)));
00305 else
00306 ereport(FATAL,
00307 (errcode(errcode_return),
00308 errmsg(errstr, port->user_name)));
00309
00310
00311 }
00312
00313
00314
00315
00316
00317
00318 void
00319 ClientAuthentication(Port *port)
00320 {
00321 int status = STATUS_ERROR;
00322
00323
00324
00325
00326
00327
00328
00329 hba_getauthmethod(port);
00330
00331
00332
00333
00334
00335
00336 ImmediateInterruptOK = true;
00337
00338 CHECK_FOR_INTERRUPTS();
00339
00340
00341
00342
00343
00344
00345 if (port->hba->clientcert)
00346 {
00347
00348
00349
00350
00351
00352
00353
00354 #ifdef USE_SSL
00355 if (!port->peer)
00356 {
00357 ereport(FATAL,
00358 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00359 errmsg("connection requires a valid client certificate")));
00360 }
00361 #else
00362
00363
00364
00365
00366
00367 Assert(false);
00368 #endif
00369 }
00370
00371
00372
00373
00374 switch (port->hba->auth_method)
00375 {
00376 case uaReject:
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 {
00389 char hostinfo[NI_MAXHOST];
00390
00391 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
00392 hostinfo, sizeof(hostinfo),
00393 NULL, 0,
00394 NI_NUMERICHOST);
00395
00396 if (am_walsender)
00397 {
00398 #ifdef USE_SSL
00399 ereport(FATAL,
00400 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00401 errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
00402 hostinfo, port->user_name,
00403 port->ssl ? _("SSL on") : _("SSL off"))));
00404 #else
00405 ereport(FATAL,
00406 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00407 errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\"",
00408 hostinfo, port->user_name)));
00409 #endif
00410 }
00411 else
00412 {
00413 #ifdef USE_SSL
00414 ereport(FATAL,
00415 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00416 errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
00417 hostinfo, port->user_name,
00418 port->database_name,
00419 port->ssl ? _("SSL on") : _("SSL off"))));
00420 #else
00421 ereport(FATAL,
00422 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00423 errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\"",
00424 hostinfo, port->user_name,
00425 port->database_name)));
00426 #endif
00427 }
00428 break;
00429 }
00430
00431 case uaImplicitReject:
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 {
00442 char hostinfo[NI_MAXHOST];
00443
00444 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
00445 hostinfo, sizeof(hostinfo),
00446 NULL, 0,
00447 NI_NUMERICHOST);
00448
00449 #define HOSTNAME_LOOKUP_DETAIL(port) \
00450 (port->remote_hostname \
00451 ? (port->remote_hostname_resolv == +1 \
00452 ? errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", port->remote_hostname) \
00453 : (port->remote_hostname_resolv == 0 \
00454 ? errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", port->remote_hostname) \
00455 : (port->remote_hostname_resolv == -1 \
00456 ? errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", port->remote_hostname) \
00457 : 0))) \
00458 : 0)
00459
00460 if (am_walsender)
00461 {
00462 #ifdef USE_SSL
00463 ereport(FATAL,
00464 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00465 errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
00466 hostinfo, port->user_name,
00467 port->ssl ? _("SSL on") : _("SSL off")),
00468 HOSTNAME_LOOKUP_DETAIL(port)));
00469 #else
00470 ereport(FATAL,
00471 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00472 errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\"",
00473 hostinfo, port->user_name),
00474 HOSTNAME_LOOKUP_DETAIL(port)));
00475 #endif
00476 }
00477 else
00478 {
00479 #ifdef USE_SSL
00480 ereport(FATAL,
00481 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00482 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
00483 hostinfo, port->user_name,
00484 port->database_name,
00485 port->ssl ? _("SSL on") : _("SSL off")),
00486 HOSTNAME_LOOKUP_DETAIL(port)));
00487 #else
00488 ereport(FATAL,
00489 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00490 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
00491 hostinfo, port->user_name,
00492 port->database_name),
00493 HOSTNAME_LOOKUP_DETAIL(port)));
00494 #endif
00495 }
00496 break;
00497 }
00498
00499 case uaKrb5:
00500 #ifdef KRB5
00501 sendAuthRequest(port, AUTH_REQ_KRB5);
00502 status = pg_krb5_recvauth(port);
00503 #else
00504 Assert(false);
00505 #endif
00506 break;
00507
00508 case uaGSS:
00509 #ifdef ENABLE_GSS
00510 sendAuthRequest(port, AUTH_REQ_GSS);
00511 status = pg_GSS_recvauth(port);
00512 #else
00513 Assert(false);
00514 #endif
00515 break;
00516
00517 case uaSSPI:
00518 #ifdef ENABLE_SSPI
00519 sendAuthRequest(port, AUTH_REQ_SSPI);
00520 status = pg_SSPI_recvauth(port);
00521 #else
00522 Assert(false);
00523 #endif
00524 break;
00525
00526 case uaPeer:
00527 #ifdef HAVE_UNIX_SOCKETS
00528 status = auth_peer(port);
00529 #else
00530 Assert(false);
00531 #endif
00532 break;
00533
00534 case uaIdent:
00535 status = ident_inet(port);
00536 break;
00537
00538 case uaMD5:
00539 if (Db_user_namespace)
00540 ereport(FATAL,
00541 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00542 errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
00543 sendAuthRequest(port, AUTH_REQ_MD5);
00544 status = recv_and_check_password_packet(port);
00545 break;
00546
00547 case uaPassword:
00548 sendAuthRequest(port, AUTH_REQ_PASSWORD);
00549 status = recv_and_check_password_packet(port);
00550 break;
00551
00552 case uaPAM:
00553 #ifdef USE_PAM
00554 status = CheckPAMAuth(port, port->user_name, "");
00555 #else
00556 Assert(false);
00557 #endif
00558 break;
00559
00560 case uaLDAP:
00561 #ifdef USE_LDAP
00562 status = CheckLDAPAuth(port);
00563 #else
00564 Assert(false);
00565 #endif
00566 break;
00567
00568 case uaCert:
00569 #ifdef USE_SSL
00570 status = CheckCertAuth(port);
00571 #else
00572 Assert(false);
00573 #endif
00574 break;
00575 case uaRADIUS:
00576 status = CheckRADIUSAuth(port);
00577 break;
00578 case uaTrust:
00579 status = STATUS_OK;
00580 break;
00581 }
00582
00583 if (ClientAuthentication_hook)
00584 (*ClientAuthentication_hook) (port, status);
00585
00586 if (status == STATUS_OK)
00587 sendAuthRequest(port, AUTH_REQ_OK);
00588 else
00589 auth_failed(port, status);
00590
00591
00592 ImmediateInterruptOK = false;
00593 }
00594
00595
00596
00597
00598
00599 static void
00600 sendAuthRequest(Port *port, AuthRequest areq)
00601 {
00602 StringInfoData buf;
00603
00604 pq_beginmessage(&buf, 'R');
00605 pq_sendint(&buf, (int32) areq, sizeof(int32));
00606
00607
00608 if (areq == AUTH_REQ_MD5)
00609 pq_sendbytes(&buf, port->md5Salt, 4);
00610
00611 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
00612
00613
00614
00615
00616
00617 else if (areq == AUTH_REQ_GSS_CONT)
00618 {
00619 if (port->gss->outbuf.length > 0)
00620 {
00621 elog(DEBUG4, "sending GSS token of length %u",
00622 (unsigned int) port->gss->outbuf.length);
00623
00624 pq_sendbytes(&buf, port->gss->outbuf.value, port->gss->outbuf.length);
00625 }
00626 }
00627 #endif
00628
00629 pq_endmessage(&buf);
00630
00631
00632
00633
00634
00635 if (areq != AUTH_REQ_OK)
00636 pq_flush();
00637 }
00638
00639
00640
00641
00642
00643
00644 static char *
00645 recv_password_packet(Port *port)
00646 {
00647 StringInfoData buf;
00648
00649 if (PG_PROTOCOL_MAJOR(port->proto) >= 3)
00650 {
00651
00652 int mtype;
00653
00654 mtype = pq_getbyte();
00655 if (mtype != 'p')
00656 {
00657
00658
00659
00660
00661
00662
00663 if (mtype != EOF)
00664 ereport(COMMERROR,
00665 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00666 errmsg("expected password response, got message type %d",
00667 mtype)));
00668 return NULL;
00669 }
00670 }
00671 else
00672 {
00673
00674 if (pq_peekbyte() == EOF)
00675 return NULL;
00676 }
00677
00678 initStringInfo(&buf);
00679 if (pq_getmessage(&buf, 1000))
00680 {
00681
00682 pfree(buf.data);
00683 return NULL;
00684 }
00685
00686
00687
00688
00689
00690
00691 if (strlen(buf.data) + 1 != buf.len)
00692 ereport(COMMERROR,
00693 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00694 errmsg("invalid password packet size")));
00695
00696
00697 ereport(DEBUG5,
00698 (errmsg("received password packet")));
00699
00700
00701
00702
00703
00704
00705 return buf.data;
00706 }
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 static int
00719 recv_and_check_password_packet(Port *port)
00720 {
00721 char *passwd;
00722 int result;
00723
00724 passwd = recv_password_packet(port);
00725
00726 if (passwd == NULL)
00727 return STATUS_EOF;
00728
00729 result = md5_crypt_verify(port, port->user_name, passwd);
00730
00731 pfree(passwd);
00732
00733 return result;
00734 }
00735
00736
00737
00738
00739
00740
00741 #ifdef KRB5
00742
00743 static int
00744 pg_krb5_init(Port *port)
00745 {
00746 krb5_error_code retval;
00747 char *khostname;
00748
00749 if (pg_krb5_initialised)
00750 return STATUS_OK;
00751
00752 retval = krb5_init_context(&pg_krb5_context);
00753 if (retval)
00754 {
00755 ereport(LOG,
00756 (errmsg("Kerberos initialization returned error %d",
00757 retval)));
00758 com_err("postgres", retval, "while initializing krb5");
00759 return STATUS_ERROR;
00760 }
00761
00762 retval = krb5_kt_resolve(pg_krb5_context, pg_krb_server_keyfile, &pg_krb5_keytab);
00763 if (retval)
00764 {
00765 ereport(LOG,
00766 (errmsg("Kerberos keytab resolving returned error %d",
00767 retval)));
00768 com_err("postgres", retval, "while resolving keytab file \"%s\"",
00769 pg_krb_server_keyfile);
00770 krb5_free_context(pg_krb5_context);
00771 return STATUS_ERROR;
00772 }
00773
00774
00775
00776
00777
00778 khostname = port->hba->krb_server_hostname;
00779 if (khostname && khostname[0] == '\0')
00780 khostname = NULL;
00781
00782 retval = krb5_sname_to_principal(pg_krb5_context,
00783 khostname,
00784 pg_krb_srvnam,
00785 KRB5_NT_SRV_HST,
00786 &pg_krb5_server);
00787 if (retval)
00788 {
00789 ereport(LOG,
00790 (errmsg("Kerberos sname_to_principal(\"%s\", \"%s\") returned error %d",
00791 khostname ? khostname : "server hostname", pg_krb_srvnam, retval)));
00792 com_err("postgres", retval,
00793 "while getting server principal for server \"%s\" for service \"%s\"",
00794 khostname ? khostname : "server hostname", pg_krb_srvnam);
00795 krb5_kt_close(pg_krb5_context, pg_krb5_keytab);
00796 krb5_free_context(pg_krb5_context);
00797 return STATUS_ERROR;
00798 }
00799
00800 pg_krb5_initialised = 1;
00801 return STATUS_OK;
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815 static int
00816 pg_krb5_recvauth(Port *port)
00817 {
00818 krb5_error_code retval;
00819 int ret;
00820 krb5_auth_context auth_context = NULL;
00821 krb5_ticket *ticket;
00822 char *kusername;
00823 char *cp;
00824
00825 ret = pg_krb5_init(port);
00826 if (ret != STATUS_OK)
00827 return ret;
00828
00829 retval = krb5_recvauth(pg_krb5_context, &auth_context,
00830 (krb5_pointer) &port->sock, pg_krb_srvnam,
00831 pg_krb5_server, 0, pg_krb5_keytab, &ticket);
00832 if (retval)
00833 {
00834 ereport(LOG,
00835 (errmsg("Kerberos recvauth returned error %d",
00836 retval)));
00837 com_err("postgres", retval, "from krb5_recvauth");
00838 return STATUS_ERROR;
00839 }
00840
00841
00842
00843
00844
00845
00846 #if defined(HAVE_KRB5_TICKET_ENC_PART2)
00847 retval = krb5_unparse_name(pg_krb5_context,
00848 ticket->enc_part2->client, &kusername);
00849 #elif defined(HAVE_KRB5_TICKET_CLIENT)
00850 retval = krb5_unparse_name(pg_krb5_context,
00851 ticket->client, &kusername);
00852 #else
00853 #error "bogus configuration"
00854 #endif
00855 if (retval)
00856 {
00857 ereport(LOG,
00858 (errmsg("Kerberos unparse_name returned error %d",
00859 retval)));
00860 com_err("postgres", retval, "while unparsing client name");
00861 krb5_free_ticket(pg_krb5_context, ticket);
00862 krb5_auth_con_free(pg_krb5_context, auth_context);
00863 return STATUS_ERROR;
00864 }
00865
00866 cp = strchr(kusername, '@');
00867 if (cp)
00868 {
00869
00870
00871
00872
00873
00874 if (!port->hba->include_realm)
00875 *cp = '\0';
00876 cp++;
00877
00878 if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
00879 {
00880
00881 if (pg_krb_caseins_users)
00882 ret = pg_strcasecmp(port->hba->krb_realm, cp);
00883 else
00884 ret = strcmp(port->hba->krb_realm, cp);
00885
00886 if (ret)
00887 {
00888 elog(DEBUG2,
00889 "krb5 realm (%s) and configured realm (%s) don't match",
00890 cp, port->hba->krb_realm);
00891
00892 krb5_free_ticket(pg_krb5_context, ticket);
00893 krb5_auth_con_free(pg_krb5_context, auth_context);
00894 return STATUS_ERROR;
00895 }
00896 }
00897 }
00898 else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
00899 {
00900 elog(DEBUG2,
00901 "krb5 did not return realm but realm matching was requested");
00902
00903 krb5_free_ticket(pg_krb5_context, ticket);
00904 krb5_auth_con_free(pg_krb5_context, auth_context);
00905 return STATUS_ERROR;
00906 }
00907
00908 ret = check_usermap(port->hba->usermap, port->user_name, kusername,
00909 pg_krb_caseins_users);
00910
00911 krb5_free_ticket(pg_krb5_context, ticket);
00912 krb5_auth_con_free(pg_krb5_context, auth_context);
00913 free(kusername);
00914
00915 return ret;
00916 }
00917 #endif
00918
00919
00920
00921
00922
00923
00924 #ifdef ENABLE_GSS
00925
00926 #if defined(WIN32) && !defined(WIN32_ONLY_COMPILER)
00927
00928
00929
00930
00931
00932 static const gss_OID_desc GSS_C_NT_USER_NAME_desc =
00933 {10, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"};
00934 static GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME = &GSS_C_NT_USER_NAME_desc;
00935 #endif
00936
00937
00938 static void
00939 pg_GSS_error(int severity, char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
00940 {
00941 gss_buffer_desc gmsg;
00942 OM_uint32 lmin_s,
00943 msg_ctx;
00944 char msg_major[128],
00945 msg_minor[128];
00946
00947
00948 msg_ctx = 0;
00949 gss_display_status(&lmin_s, maj_stat, GSS_C_GSS_CODE,
00950 GSS_C_NO_OID, &msg_ctx, &gmsg);
00951 strlcpy(msg_major, gmsg.value, sizeof(msg_major));
00952 gss_release_buffer(&lmin_s, &gmsg);
00953
00954 if (msg_ctx)
00955
00956
00957
00958
00959
00960 ereport(WARNING,
00961 (errmsg_internal("incomplete GSS error report")));
00962
00963
00964 msg_ctx = 0;
00965 gss_display_status(&lmin_s, min_stat, GSS_C_MECH_CODE,
00966 GSS_C_NO_OID, &msg_ctx, &gmsg);
00967 strlcpy(msg_minor, gmsg.value, sizeof(msg_minor));
00968 gss_release_buffer(&lmin_s, &gmsg);
00969
00970 if (msg_ctx)
00971 ereport(WARNING,
00972 (errmsg_internal("incomplete GSS minor error report")));
00973
00974
00975
00976
00977
00978 ereport(severity,
00979 (errmsg_internal("%s", errmsg),
00980 errdetail_internal("%s: %s", msg_major, msg_minor)));
00981 }
00982
00983 static int
00984 pg_GSS_recvauth(Port *port)
00985 {
00986 OM_uint32 maj_stat,
00987 min_stat,
00988 lmin_s,
00989 gflags;
00990 int mtype;
00991 int ret;
00992 StringInfoData buf;
00993 gss_buffer_desc gbuf;
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
01004 ereport(FATAL,
01005 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01006 errmsg("GSSAPI is not supported in protocol version 2")));
01007
01008 if (pg_krb_server_keyfile && strlen(pg_krb_server_keyfile) > 0)
01009 {
01010
01011
01012
01013
01014
01015
01016 if (getenv("KRB5_KTNAME") == NULL)
01017 {
01018 size_t kt_len = strlen(pg_krb_server_keyfile) + 14;
01019 char *kt_path = malloc(kt_len);
01020
01021 if (!kt_path)
01022 {
01023 ereport(LOG,
01024 (errcode(ERRCODE_OUT_OF_MEMORY),
01025 errmsg("out of memory")));
01026 return STATUS_ERROR;
01027 }
01028 snprintf(kt_path, kt_len, "KRB5_KTNAME=%s", pg_krb_server_keyfile);
01029 putenv(kt_path);
01030 }
01031 }
01032
01033
01034
01035
01036
01037
01038
01039 port->gss->cred = GSS_C_NO_CREDENTIAL;
01040
01041
01042
01043
01044 port->gss->ctx = GSS_C_NO_CONTEXT;
01045
01046
01047
01048
01049
01050
01051
01052 do
01053 {
01054 mtype = pq_getbyte();
01055 if (mtype != 'p')
01056 {
01057
01058 if (mtype != EOF)
01059 ereport(COMMERROR,
01060 (errcode(ERRCODE_PROTOCOL_VIOLATION),
01061 errmsg("expected GSS response, got message type %d",
01062 mtype)));
01063 return STATUS_ERROR;
01064 }
01065
01066
01067 initStringInfo(&buf);
01068 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))
01069 {
01070
01071 pfree(buf.data);
01072 return STATUS_ERROR;
01073 }
01074
01075
01076 gbuf.length = buf.len;
01077 gbuf.value = buf.data;
01078
01079 elog(DEBUG4, "Processing received GSS token of length %u",
01080 (unsigned int) gbuf.length);
01081
01082 maj_stat = gss_accept_sec_context(
01083 &min_stat,
01084 &port->gss->ctx,
01085 port->gss->cred,
01086 &gbuf,
01087 GSS_C_NO_CHANNEL_BINDINGS,
01088 &port->gss->name,
01089 NULL,
01090 &port->gss->outbuf,
01091 &gflags,
01092 NULL,
01093 NULL);
01094
01095
01096 pfree(buf.data);
01097
01098 elog(DEBUG5, "gss_accept_sec_context major: %d, "
01099 "minor: %d, outlen: %u, outflags: %x",
01100 maj_stat, min_stat,
01101 (unsigned int) port->gss->outbuf.length, gflags);
01102
01103 if (port->gss->outbuf.length != 0)
01104 {
01105
01106
01107
01108 elog(DEBUG4, "sending GSS response token of length %u",
01109 (unsigned int) port->gss->outbuf.length);
01110
01111 sendAuthRequest(port, AUTH_REQ_GSS_CONT);
01112
01113 gss_release_buffer(&lmin_s, &port->gss->outbuf);
01114 }
01115
01116 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
01117 {
01118 gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
01119 pg_GSS_error(ERROR,
01120 gettext_noop("accepting GSS security context failed"),
01121 maj_stat, min_stat);
01122 }
01123
01124 if (maj_stat == GSS_S_CONTINUE_NEEDED)
01125 elog(DEBUG4, "GSS continue needed");
01126
01127 } while (maj_stat == GSS_S_CONTINUE_NEEDED);
01128
01129 if (port->gss->cred != GSS_C_NO_CREDENTIAL)
01130 {
01131
01132
01133
01134 gss_release_cred(&min_stat, &port->gss->cred);
01135 }
01136
01137
01138
01139
01140
01141
01142
01143 maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
01144 if (maj_stat != GSS_S_COMPLETE)
01145 pg_GSS_error(ERROR,
01146 gettext_noop("retrieving GSS user name failed"),
01147 maj_stat, min_stat);
01148
01149
01150
01151
01152 if (strchr(gbuf.value, '@'))
01153 {
01154 char *cp = strchr(gbuf.value, '@');
01155
01156
01157
01158
01159
01160
01161 if (!port->hba->include_realm)
01162 *cp = '\0';
01163 cp++;
01164
01165 if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
01166 {
01167
01168
01169
01170 if (pg_krb_caseins_users)
01171 ret = pg_strcasecmp(port->hba->krb_realm, cp);
01172 else
01173 ret = strcmp(port->hba->krb_realm, cp);
01174
01175 if (ret)
01176 {
01177
01178 elog(DEBUG2,
01179 "GSSAPI realm (%s) and configured realm (%s) don't match",
01180 cp, port->hba->krb_realm);
01181 gss_release_buffer(&lmin_s, &gbuf);
01182 return STATUS_ERROR;
01183 }
01184 }
01185 }
01186 else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
01187 {
01188 elog(DEBUG2,
01189 "GSSAPI did not return realm but realm matching was requested");
01190
01191 gss_release_buffer(&lmin_s, &gbuf);
01192 return STATUS_ERROR;
01193 }
01194
01195 ret = check_usermap(port->hba->usermap, port->user_name, gbuf.value,
01196 pg_krb_caseins_users);
01197
01198 gss_release_buffer(&lmin_s, &gbuf);
01199
01200 return ret;
01201 }
01202 #endif
01203
01204
01205
01206
01207
01208
01209 #ifdef ENABLE_SSPI
01210 static void
01211 pg_SSPI_error(int severity, const char *errmsg, SECURITY_STATUS r)
01212 {
01213 char sysmsg[256];
01214
01215 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, r, 0,
01216 sysmsg, sizeof(sysmsg), NULL) == 0)
01217 ereport(severity,
01218 (errmsg_internal("%s", errmsg),
01219 errdetail_internal("SSPI error %x", (unsigned int) r)));
01220 else
01221 ereport(severity,
01222 (errmsg_internal("%s", errmsg),
01223 errdetail_internal("%s (%x)", sysmsg, (unsigned int) r)));
01224 }
01225
01226 static int
01227 pg_SSPI_recvauth(Port *port)
01228 {
01229 int mtype;
01230 StringInfoData buf;
01231 SECURITY_STATUS r;
01232 CredHandle sspicred;
01233 CtxtHandle *sspictx = NULL,
01234 newctx;
01235 TimeStamp expiry;
01236 ULONG contextattr;
01237 SecBufferDesc inbuf;
01238 SecBufferDesc outbuf;
01239 SecBuffer OutBuffers[1];
01240 SecBuffer InBuffers[1];
01241 HANDLE token;
01242 TOKEN_USER *tokenuser;
01243 DWORD retlen;
01244 char accountname[MAXPGPATH];
01245 char domainname[MAXPGPATH];
01246 DWORD accountnamesize = sizeof(accountname);
01247 DWORD domainnamesize = sizeof(domainname);
01248 SID_NAME_USE accountnameuse;
01249 HMODULE secur32;
01250 QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken;
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
01261 ereport(FATAL,
01262 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01263 errmsg("SSPI is not supported in protocol version 2")));
01264
01265
01266
01267
01268 r = AcquireCredentialsHandle(NULL,
01269 "negotiate",
01270 SECPKG_CRED_INBOUND,
01271 NULL,
01272 NULL,
01273 NULL,
01274 NULL,
01275 &sspicred,
01276 &expiry);
01277 if (r != SEC_E_OK)
01278 pg_SSPI_error(ERROR, _("could not acquire SSPI credentials"), r);
01279
01280
01281
01282
01283
01284
01285
01286 do
01287 {
01288 mtype = pq_getbyte();
01289 if (mtype != 'p')
01290 {
01291
01292 if (mtype != EOF)
01293 ereport(COMMERROR,
01294 (errcode(ERRCODE_PROTOCOL_VIOLATION),
01295 errmsg("expected SSPI response, got message type %d",
01296 mtype)));
01297 return STATUS_ERROR;
01298 }
01299
01300
01301 initStringInfo(&buf);
01302 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))
01303 {
01304
01305 pfree(buf.data);
01306 return STATUS_ERROR;
01307 }
01308
01309
01310 inbuf.ulVersion = SECBUFFER_VERSION;
01311 inbuf.cBuffers = 1;
01312 inbuf.pBuffers = InBuffers;
01313 InBuffers[0].pvBuffer = buf.data;
01314 InBuffers[0].cbBuffer = buf.len;
01315 InBuffers[0].BufferType = SECBUFFER_TOKEN;
01316
01317
01318 OutBuffers[0].pvBuffer = NULL;
01319 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
01320 OutBuffers[0].cbBuffer = 0;
01321 outbuf.cBuffers = 1;
01322 outbuf.pBuffers = OutBuffers;
01323 outbuf.ulVersion = SECBUFFER_VERSION;
01324
01325
01326 elog(DEBUG4, "Processing received SSPI token of length %u",
01327 (unsigned int) buf.len);
01328
01329 r = AcceptSecurityContext(&sspicred,
01330 sspictx,
01331 &inbuf,
01332 ASC_REQ_ALLOCATE_MEMORY,
01333 SECURITY_NETWORK_DREP,
01334 &newctx,
01335 &outbuf,
01336 &contextattr,
01337 NULL);
01338
01339
01340 pfree(buf.data);
01341
01342 if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
01343 {
01344
01345
01346
01347 elog(DEBUG4, "sending SSPI response token of length %u",
01348 (unsigned int) outbuf.pBuffers[0].cbBuffer);
01349
01350 port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
01351 port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
01352
01353 sendAuthRequest(port, AUTH_REQ_GSS_CONT);
01354
01355 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
01356 }
01357
01358 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
01359 {
01360 if (sspictx != NULL)
01361 {
01362 DeleteSecurityContext(sspictx);
01363 free(sspictx);
01364 }
01365 FreeCredentialsHandle(&sspicred);
01366 pg_SSPI_error(ERROR,
01367 _("could not accept SSPI security context"), r);
01368 }
01369
01370
01371
01372
01373
01374
01375
01376 if (sspictx == NULL)
01377 {
01378 sspictx = malloc(sizeof(CtxtHandle));
01379 if (sspictx == NULL)
01380 ereport(ERROR,
01381 (errmsg("out of memory")));
01382 }
01383
01384 memcpy(sspictx, &newctx, sizeof(CtxtHandle));
01385
01386 if (r == SEC_I_CONTINUE_NEEDED)
01387 elog(DEBUG4, "SSPI continue needed");
01388
01389 } while (r == SEC_I_CONTINUE_NEEDED);
01390
01391
01392
01393
01394
01395 FreeCredentialsHandle(&sspicred);
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408 secur32 = LoadLibrary("SECUR32.DLL");
01409 if (secur32 == NULL)
01410 ereport(ERROR,
01411 (errmsg_internal("could not load secur32.dll: error code %lu",
01412 GetLastError())));
01413
01414 _QuerySecurityContextToken = (QUERY_SECURITY_CONTEXT_TOKEN_FN)
01415 GetProcAddress(secur32, "QuerySecurityContextToken");
01416 if (_QuerySecurityContextToken == NULL)
01417 {
01418 FreeLibrary(secur32);
01419 ereport(ERROR,
01420 (errmsg_internal("could not locate QuerySecurityContextToken in secur32.dll: error code %lu",
01421 GetLastError())));
01422 }
01423
01424 r = (_QuerySecurityContextToken) (sspictx, &token);
01425 if (r != SEC_E_OK)
01426 {
01427 FreeLibrary(secur32);
01428 pg_SSPI_error(ERROR,
01429 _("could not get token from SSPI security context"), r);
01430 }
01431
01432 FreeLibrary(secur32);
01433
01434
01435
01436
01437
01438 DeleteSecurityContext(sspictx);
01439 free(sspictx);
01440
01441 if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
01442 ereport(ERROR,
01443 (errmsg_internal("could not get token user size: error code %lu",
01444 GetLastError())));
01445
01446 tokenuser = malloc(retlen);
01447 if (tokenuser == NULL)
01448 ereport(ERROR,
01449 (errmsg("out of memory")));
01450
01451 if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
01452 ereport(ERROR,
01453 (errmsg_internal("could not get user token: error code %lu",
01454 GetLastError())));
01455
01456 if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
01457 domainname, &domainnamesize, &accountnameuse))
01458 ereport(ERROR,
01459 (errmsg_internal("could not look up account SID: error code %lu",
01460 GetLastError())));
01461
01462 free(tokenuser);
01463
01464
01465
01466
01467
01468 if (port->hba->krb_realm && strlen(port->hba->krb_realm))
01469 {
01470 if (pg_strcasecmp(port->hba->krb_realm, domainname) != 0)
01471 {
01472 elog(DEBUG2,
01473 "SSPI domain (%s) and configured domain (%s) don't match",
01474 domainname, port->hba->krb_realm);
01475
01476 return STATUS_ERROR;
01477 }
01478 }
01479
01480
01481
01482
01483
01484
01485
01486 if (port->hba->include_realm)
01487 {
01488 char *namebuf;
01489 int retval;
01490
01491 namebuf = palloc(strlen(accountname) + strlen(domainname) + 2);
01492 sprintf(namebuf, "%s@%s", accountname, domainname);
01493 retval = check_usermap(port->hba->usermap, port->user_name, namebuf, true);
01494 pfree(namebuf);
01495 return retval;
01496 }
01497 else
01498 return check_usermap(port->hba->usermap, port->user_name, accountname, true);
01499 }
01500 #endif
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515 static bool
01516 interpret_ident_response(const char *ident_response,
01517 char *ident_user)
01518 {
01519 const char *cursor = ident_response;
01520
01521
01522
01523
01524 if (strlen(ident_response) < 2)
01525 return false;
01526 else if (ident_response[strlen(ident_response) - 2] != '\r')
01527 return false;
01528 else
01529 {
01530 while (*cursor != ':' && *cursor != '\r')
01531 cursor++;
01532
01533 if (*cursor != ':')
01534 return false;
01535 else
01536 {
01537
01538 char response_type[80];
01539 int i;
01540
01541 cursor++;
01542 while (pg_isblank(*cursor))
01543 cursor++;
01544 i = 0;
01545 while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
01546 i < (int) (sizeof(response_type) - 1))
01547 response_type[i++] = *cursor++;
01548 response_type[i] = '\0';
01549 while (pg_isblank(*cursor))
01550 cursor++;
01551 if (strcmp(response_type, "USERID") != 0)
01552 return false;
01553 else
01554 {
01555
01556
01557
01558
01559 if (*cursor != ':')
01560 return false;
01561 else
01562 {
01563 cursor++;
01564
01565 while (*cursor != ':' && *cursor != '\r')
01566 cursor++;
01567 if (*cursor != ':')
01568 return false;
01569 else
01570 {
01571 int i;
01572
01573 cursor++;
01574 while (pg_isblank(*cursor))
01575 cursor++;
01576
01577 i = 0;
01578 while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
01579 ident_user[i++] = *cursor++;
01580 ident_user[i] = '\0';
01581 return true;
01582 }
01583 }
01584 }
01585 }
01586 }
01587 }
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600 static int
01601 ident_inet(hbaPort *port)
01602 {
01603 const SockAddr remote_addr = port->raddr;
01604 const SockAddr local_addr = port->laddr;
01605 char ident_user[IDENT_USERNAME_MAX + 1];
01606 pgsocket sock_fd;
01607
01608 int rc;
01609 bool ident_return;
01610 char remote_addr_s[NI_MAXHOST];
01611 char remote_port[NI_MAXSERV];
01612 char local_addr_s[NI_MAXHOST];
01613 char local_port[NI_MAXSERV];
01614 char ident_port[NI_MAXSERV];
01615 char ident_query[80];
01616 char ident_response[80 + IDENT_USERNAME_MAX];
01617 struct addrinfo *ident_serv = NULL,
01618 *la = NULL,
01619 hints;
01620
01621
01622
01623
01624
01625 pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
01626 remote_addr_s, sizeof(remote_addr_s),
01627 remote_port, sizeof(remote_port),
01628 NI_NUMERICHOST | NI_NUMERICSERV);
01629 pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
01630 local_addr_s, sizeof(local_addr_s),
01631 local_port, sizeof(local_port),
01632 NI_NUMERICHOST | NI_NUMERICSERV);
01633
01634 snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
01635 hints.ai_flags = AI_NUMERICHOST;
01636 hints.ai_family = remote_addr.addr.ss_family;
01637 hints.ai_socktype = SOCK_STREAM;
01638 hints.ai_protocol = 0;
01639 hints.ai_addrlen = 0;
01640 hints.ai_canonname = NULL;
01641 hints.ai_addr = NULL;
01642 hints.ai_next = NULL;
01643 rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
01644 if (rc || !ident_serv)
01645 {
01646 if (ident_serv)
01647 pg_freeaddrinfo_all(hints.ai_family, ident_serv);
01648 return STATUS_ERROR;
01649 }
01650
01651 hints.ai_flags = AI_NUMERICHOST;
01652 hints.ai_family = local_addr.addr.ss_family;
01653 hints.ai_socktype = SOCK_STREAM;
01654 hints.ai_protocol = 0;
01655 hints.ai_addrlen = 0;
01656 hints.ai_canonname = NULL;
01657 hints.ai_addr = NULL;
01658 hints.ai_next = NULL;
01659 rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
01660 if (rc || !la)
01661 {
01662 if (la)
01663 pg_freeaddrinfo_all(hints.ai_family, la);
01664 return STATUS_ERROR;
01665 }
01666
01667 sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
01668 ident_serv->ai_protocol);
01669 if (sock_fd < 0)
01670 {
01671 ereport(LOG,
01672 (errcode_for_socket_access(),
01673 errmsg("could not create socket for Ident connection: %m")));
01674 ident_return = false;
01675 goto ident_inet_done;
01676 }
01677
01678
01679
01680
01681
01682
01683 rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
01684 if (rc != 0)
01685 {
01686 ereport(LOG,
01687 (errcode_for_socket_access(),
01688 errmsg("could not bind to local address \"%s\": %m",
01689 local_addr_s)));
01690 ident_return = false;
01691 goto ident_inet_done;
01692 }
01693
01694 rc = connect(sock_fd, ident_serv->ai_addr,
01695 ident_serv->ai_addrlen);
01696 if (rc != 0)
01697 {
01698 ereport(LOG,
01699 (errcode_for_socket_access(),
01700 errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
01701 remote_addr_s, ident_port)));
01702 ident_return = false;
01703 goto ident_inet_done;
01704 }
01705
01706
01707 snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
01708 remote_port, local_port);
01709
01710
01711 do
01712 {
01713 rc = send(sock_fd, ident_query, strlen(ident_query), 0);
01714 } while (rc < 0 && errno == EINTR);
01715
01716 if (rc < 0)
01717 {
01718 ereport(LOG,
01719 (errcode_for_socket_access(),
01720 errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
01721 remote_addr_s, ident_port)));
01722 ident_return = false;
01723 goto ident_inet_done;
01724 }
01725
01726 do
01727 {
01728 rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
01729 } while (rc < 0 && errno == EINTR);
01730
01731 if (rc < 0)
01732 {
01733 ereport(LOG,
01734 (errcode_for_socket_access(),
01735 errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
01736 remote_addr_s, ident_port)));
01737 ident_return = false;
01738 goto ident_inet_done;
01739 }
01740
01741 ident_response[rc] = '\0';
01742 ident_return = interpret_ident_response(ident_response, ident_user);
01743 if (!ident_return)
01744 ereport(LOG,
01745 (errmsg("invalidly formatted response from Ident server: \"%s\"",
01746 ident_response)));
01747
01748 ident_inet_done:
01749 if (sock_fd >= 0)
01750 closesocket(sock_fd);
01751 pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
01752 pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
01753
01754 if (ident_return)
01755
01756 return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
01757 return STATUS_ERROR;
01758 }
01759
01760
01761
01762
01763
01764
01765
01766
01767 #ifdef HAVE_UNIX_SOCKETS
01768
01769 static int
01770 auth_peer(hbaPort *port)
01771 {
01772 char ident_user[IDENT_USERNAME_MAX + 1];
01773 uid_t uid;
01774 gid_t gid;
01775 struct passwd *pass;
01776
01777 errno = 0;
01778 if (getpeereid(port->sock, &uid, &gid) != 0)
01779 {
01780
01781 if (errno == ENOSYS)
01782 ereport(LOG,
01783 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01784 errmsg("peer authentication is not supported on this platform")));
01785 else
01786 ereport(LOG,
01787 (errcode_for_socket_access(),
01788 errmsg("could not get peer credentials: %m")));
01789 return STATUS_ERROR;
01790 }
01791
01792 pass = getpwuid(uid);
01793
01794 if (pass == NULL)
01795 {
01796 ereport(LOG,
01797 (errmsg("local user with ID %d does not exist",
01798 (int) uid)));
01799 return STATUS_ERROR;
01800 }
01801
01802 strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
01803
01804 return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
01805 }
01806 #endif
01807
01808
01809
01810
01811
01812
01813 #ifdef USE_PAM
01814
01815
01816
01817
01818
01819 static int
01820 pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
01821 struct pam_response ** resp, void *appdata_ptr)
01822 {
01823 char *passwd;
01824 struct pam_response *reply;
01825 int i;
01826
01827 if (appdata_ptr)
01828 passwd = (char *) appdata_ptr;
01829 else
01830 {
01831
01832
01833
01834
01835 passwd = pam_passwd;
01836 }
01837
01838 *resp = NULL;
01839
01840 if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG)
01841 return PAM_CONV_ERR;
01842
01843
01844
01845
01846
01847 if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL)
01848 {
01849 ereport(LOG,
01850 (errcode(ERRCODE_OUT_OF_MEMORY),
01851 errmsg("out of memory")));
01852 return PAM_CONV_ERR;
01853 }
01854
01855 for (i = 0; i < num_msg; i++)
01856 {
01857 switch (msg[i]->msg_style)
01858 {
01859 case PAM_PROMPT_ECHO_OFF:
01860 if (strlen(passwd) == 0)
01861 {
01862
01863
01864
01865
01866
01867 sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD);
01868 passwd = recv_password_packet(pam_port_cludge);
01869 if (passwd == NULL)
01870 {
01871
01872
01873
01874
01875 goto fail;
01876 }
01877 if (strlen(passwd) == 0)
01878 {
01879 ereport(LOG,
01880 (errmsg("empty password returned by client")));
01881 goto fail;
01882 }
01883 }
01884 if ((reply[i].resp = strdup(passwd)) == NULL)
01885 goto fail;
01886 reply[i].resp_retcode = PAM_SUCCESS;
01887 break;
01888 case PAM_ERROR_MSG:
01889 ereport(LOG,
01890 (errmsg("error from underlying PAM layer: %s",
01891 msg[i]->msg)));
01892
01893 case PAM_TEXT_INFO:
01894
01895 if ((reply[i].resp = strdup("")) == NULL)
01896 goto fail;
01897 reply[i].resp_retcode = PAM_SUCCESS;
01898 break;
01899 default:
01900 elog(LOG, "unsupported PAM conversation %d/\"%s\"",
01901 msg[i]->msg_style,
01902 msg[i]->msg ? msg[i]->msg : "(none)");
01903 goto fail;
01904 }
01905 }
01906
01907 *resp = reply;
01908 return PAM_SUCCESS;
01909
01910 fail:
01911
01912 for (i = 0; i < num_msg; i++)
01913 {
01914 if (reply[i].resp != NULL)
01915 free(reply[i].resp);
01916 }
01917 free(reply);
01918
01919 return PAM_CONV_ERR;
01920 }
01921
01922
01923
01924
01925
01926 static int
01927 CheckPAMAuth(Port *port, char *user, char *password)
01928 {
01929 int retval;
01930 pam_handle_t *pamh = NULL;
01931
01932
01933
01934
01935
01936
01937 pam_passwd = password;
01938 pam_port_cludge = port;
01939
01940
01941
01942
01943
01944
01945 pam_passw_conv.appdata_ptr = (char *) password;
01946
01947
01948
01949 if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
01950 retval = pam_start(port->hba->pamservice, "pgsql@",
01951 &pam_passw_conv, &pamh);
01952 else
01953 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
01954 &pam_passw_conv, &pamh);
01955
01956 if (retval != PAM_SUCCESS)
01957 {
01958 ereport(LOG,
01959 (errmsg("could not create PAM authenticator: %s",
01960 pam_strerror(pamh, retval))));
01961 pam_passwd = NULL;
01962 return STATUS_ERROR;
01963 }
01964
01965 retval = pam_set_item(pamh, PAM_USER, user);
01966
01967 if (retval != PAM_SUCCESS)
01968 {
01969 ereport(LOG,
01970 (errmsg("pam_set_item(PAM_USER) failed: %s",
01971 pam_strerror(pamh, retval))));
01972 pam_passwd = NULL;
01973 return STATUS_ERROR;
01974 }
01975
01976 retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
01977
01978 if (retval != PAM_SUCCESS)
01979 {
01980 ereport(LOG,
01981 (errmsg("pam_set_item(PAM_CONV) failed: %s",
01982 pam_strerror(pamh, retval))));
01983 pam_passwd = NULL;
01984 return STATUS_ERROR;
01985 }
01986
01987 retval = pam_authenticate(pamh, 0);
01988
01989 if (retval != PAM_SUCCESS)
01990 {
01991 ereport(LOG,
01992 (errmsg("pam_authenticate failed: %s",
01993 pam_strerror(pamh, retval))));
01994 pam_passwd = NULL;
01995 return STATUS_ERROR;
01996 }
01997
01998 retval = pam_acct_mgmt(pamh, 0);
01999
02000 if (retval != PAM_SUCCESS)
02001 {
02002 ereport(LOG,
02003 (errmsg("pam_acct_mgmt failed: %s",
02004 pam_strerror(pamh, retval))));
02005 pam_passwd = NULL;
02006 return STATUS_ERROR;
02007 }
02008
02009 retval = pam_end(pamh, retval);
02010
02011 if (retval != PAM_SUCCESS)
02012 {
02013 ereport(LOG,
02014 (errmsg("could not release PAM authenticator: %s",
02015 pam_strerror(pamh, retval))));
02016 }
02017
02018 pam_passwd = NULL;
02019
02020 return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
02021 }
02022 #endif
02023
02024
02025
02026
02027
02028
02029
02030 #ifdef USE_LDAP
02031
02032
02033
02034
02035
02036 static int
02037 InitializeLDAPConnection(Port *port, LDAP **ldap)
02038 {
02039 int ldapversion = LDAP_VERSION3;
02040 int r;
02041
02042 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
02043 if (!*ldap)
02044 {
02045 #ifndef WIN32
02046 ereport(LOG,
02047 (errmsg("could not initialize LDAP: %m")));
02048 #else
02049 ereport(LOG,
02050 (errmsg("could not initialize LDAP: error code %d",
02051 (int) LdapGetLastError())));
02052 #endif
02053 return STATUS_ERROR;
02054 }
02055
02056 if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
02057 {
02058 ldap_unbind(*ldap);
02059 ereport(LOG,
02060 (errmsg("could not set LDAP protocol version: %s", ldap_err2string(r))));
02061 return STATUS_ERROR;
02062 }
02063
02064 if (port->hba->ldaptls)
02065 {
02066 #ifndef WIN32
02067 if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)
02068 #else
02069 static __ldap_start_tls_sA _ldap_start_tls_sA = NULL;
02070
02071 if (_ldap_start_tls_sA == NULL)
02072 {
02073
02074
02075
02076
02077
02078 HANDLE ldaphandle;
02079
02080 ldaphandle = LoadLibrary("WLDAP32.DLL");
02081 if (ldaphandle == NULL)
02082 {
02083
02084
02085
02086
02087 ldap_unbind(*ldap);
02088 ereport(LOG,
02089 (errmsg("could not load wldap32.dll")));
02090 return STATUS_ERROR;
02091 }
02092 _ldap_start_tls_sA = (__ldap_start_tls_sA) GetProcAddress(ldaphandle, "ldap_start_tls_sA");
02093 if (_ldap_start_tls_sA == NULL)
02094 {
02095 ldap_unbind(*ldap);
02096 ereport(LOG,
02097 (errmsg("could not load function _ldap_start_tls_sA in wldap32.dll"),
02098 errdetail("LDAP over SSL is not supported on this platform.")));
02099 return STATUS_ERROR;
02100 }
02101
02102
02103
02104
02105
02106
02107 }
02108 if ((r = _ldap_start_tls_sA(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
02109 #endif
02110 {
02111 ldap_unbind(*ldap);
02112 ereport(LOG,
02113 (errmsg("could not start LDAP TLS session: %s", ldap_err2string(r))));
02114 return STATUS_ERROR;
02115 }
02116 }
02117
02118 return STATUS_OK;
02119 }
02120
02121
02122
02123
02124 static int
02125 CheckLDAPAuth(Port *port)
02126 {
02127 char *passwd;
02128 LDAP *ldap;
02129 int r;
02130 char *fulluser;
02131
02132 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
02133 {
02134 ereport(LOG,
02135 (errmsg("LDAP server not specified")));
02136 return STATUS_ERROR;
02137 }
02138
02139 if (port->hba->ldapport == 0)
02140 port->hba->ldapport = LDAP_PORT;
02141
02142 sendAuthRequest(port, AUTH_REQ_PASSWORD);
02143
02144 passwd = recv_password_packet(port);
02145 if (passwd == NULL)
02146 return STATUS_EOF;
02147
02148 if (strlen(passwd) == 0)
02149 {
02150 ereport(LOG,
02151 (errmsg("empty password returned by client")));
02152 return STATUS_ERROR;
02153 }
02154
02155 if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
02156
02157 return STATUS_ERROR;
02158
02159 if (port->hba->ldapbasedn)
02160 {
02161
02162
02163
02164
02165 char *filter;
02166 LDAPMessage *search_message;
02167 LDAPMessage *entry;
02168 char *attributes[2];
02169 char *dn;
02170 char *c;
02171 int count;
02172
02173
02174
02175
02176
02177
02178
02179 for (c = port->user_name; *c; c++)
02180 {
02181 if (*c == '*' ||
02182 *c == '(' ||
02183 *c == ')' ||
02184 *c == '\\' ||
02185 *c == '/')
02186 {
02187 ereport(LOG,
02188 (errmsg("invalid character in user name for LDAP authentication")));
02189 return STATUS_ERROR;
02190 }
02191 }
02192
02193
02194
02195
02196
02197 r = ldap_simple_bind_s(ldap,
02198 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
02199 port->hba->ldapbindpasswd ? port->hba->ldapbindpasswd : "");
02200 if (r != LDAP_SUCCESS)
02201 {
02202 ereport(LOG,
02203 (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s",
02204 port->hba->ldapbinddn, port->hba->ldapserver, ldap_err2string(r))));
02205 return STATUS_ERROR;
02206 }
02207
02208
02209 attributes[0] = port->hba->ldapsearchattribute ? port->hba->ldapsearchattribute : "uid";
02210 attributes[1] = NULL;
02211
02212 filter = palloc(strlen(attributes[0]) + strlen(port->user_name) + 4);
02213 sprintf(filter, "(%s=%s)",
02214 attributes[0],
02215 port->user_name);
02216
02217 r = ldap_search_s(ldap,
02218 port->hba->ldapbasedn,
02219 port->hba->ldapscope,
02220 filter,
02221 attributes,
02222 0,
02223 &search_message);
02224
02225 if (r != LDAP_SUCCESS)
02226 {
02227 ereport(LOG,
02228 (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s",
02229 filter, port->hba->ldapserver, ldap_err2string(r))));
02230 pfree(filter);
02231 return STATUS_ERROR;
02232 }
02233
02234 count = ldap_count_entries(ldap, search_message);
02235 if (count != 1)
02236 {
02237 if (count == 0)
02238 ereport(LOG,
02239 (errmsg("LDAP user \"%s\" does not exist", port->user_name),
02240 errdetail("LDAP search for filter \"%s\" on server \"%s\" returned no entries.",
02241 filter, port->hba->ldapserver)));
02242 else
02243 ereport(LOG,
02244 (errmsg("LDAP user \"%s\" is not unique", port->user_name),
02245 errdetail_plural("LDAP search for filter \"%s\" on server \"%s\" returned %d entry.",
02246 "LDAP search for filter \"%s\" on server \"%s\" returned %d entries.",
02247 count,
02248 filter, port->hba->ldapserver, count)));
02249
02250 pfree(filter);
02251 ldap_msgfree(search_message);
02252 return STATUS_ERROR;
02253 }
02254
02255 entry = ldap_first_entry(ldap, search_message);
02256 dn = ldap_get_dn(ldap, entry);
02257 if (dn == NULL)
02258 {
02259 int error;
02260
02261 (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);
02262 ereport(LOG,
02263 (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
02264 filter, port->hba->ldapserver, ldap_err2string(error))));
02265 pfree(filter);
02266 ldap_msgfree(search_message);
02267 return STATUS_ERROR;
02268 }
02269 fulluser = pstrdup(dn);
02270
02271 pfree(filter);
02272 ldap_memfree(dn);
02273 ldap_msgfree(search_message);
02274
02275
02276 r = ldap_unbind_s(ldap);
02277 if (r != LDAP_SUCCESS)
02278 {
02279 int error;
02280
02281 (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);
02282 ereport(LOG,
02283 (errmsg("could not unbind after searching for user \"%s\" on server \"%s\": %s",
02284 fulluser, port->hba->ldapserver, ldap_err2string(error))));
02285 pfree(fulluser);
02286 return STATUS_ERROR;
02287 }
02288
02289
02290
02291
02292
02293 if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
02294 {
02295 pfree(fulluser);
02296
02297
02298 return STATUS_ERROR;
02299 }
02300 }
02301 else
02302 {
02303 fulluser = palloc((port->hba->ldapprefix ? strlen(port->hba->ldapprefix) : 0) +
02304 strlen(port->user_name) +
02305 (port->hba->ldapsuffix ? strlen(port->hba->ldapsuffix) : 0) +
02306 1);
02307
02308 sprintf(fulluser, "%s%s%s",
02309 port->hba->ldapprefix ? port->hba->ldapprefix : "",
02310 port->user_name,
02311 port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
02312 }
02313
02314 r = ldap_simple_bind_s(ldap, fulluser, passwd);
02315 ldap_unbind(ldap);
02316
02317 if (r != LDAP_SUCCESS)
02318 {
02319 ereport(LOG,
02320 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s",
02321 fulluser, port->hba->ldapserver, ldap_err2string(r))));
02322 pfree(fulluser);
02323 return STATUS_ERROR;
02324 }
02325
02326 pfree(fulluser);
02327
02328 return STATUS_OK;
02329 }
02330 #endif
02331
02332
02333
02334
02335
02336
02337 #ifdef USE_SSL
02338 static int
02339 CheckCertAuth(Port *port)
02340 {
02341 Assert(port->ssl);
02342
02343
02344 if (port->peer_cn == NULL ||
02345 strlen(port->peer_cn) <= 0)
02346 {
02347 ereport(LOG,
02348 (errmsg("certificate authentication failed for user \"%s\": client certificate contains no user name",
02349 port->user_name)));
02350 return STATUS_ERROR;
02351 }
02352
02353
02354 return check_usermap(port->hba->usermap, port->user_name, port->peer_cn, false);
02355 }
02356 #endif
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369 #define RADIUS_VECTOR_LENGTH 16
02370 #define RADIUS_HEADER_LENGTH 20
02371
02372 typedef struct
02373 {
02374 uint8 attribute;
02375 uint8 length;
02376 uint8 data[1];
02377 } radius_attribute;
02378
02379 typedef struct
02380 {
02381 uint8 code;
02382 uint8 id;
02383 uint16 length;
02384 uint8 vector[RADIUS_VECTOR_LENGTH];
02385 } radius_packet;
02386
02387
02388 #define RADIUS_ACCESS_REQUEST 1
02389 #define RADIUS_ACCESS_ACCEPT 2
02390 #define RADIUS_ACCESS_REJECT 3
02391
02392
02393 #define RADIUS_USER_NAME 1
02394 #define RADIUS_PASSWORD 2
02395 #define RADIUS_SERVICE_TYPE 6
02396 #define RADIUS_NAS_IDENTIFIER 32
02397
02398
02399 #define RADIUS_AUTHENTICATE_ONLY 8
02400
02401
02402 #define RADIUS_BUFFER_SIZE 1024
02403
02404
02405 #define RADIUS_TIMEOUT 3
02406
02407 static void
02408 radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
02409 {
02410 radius_attribute *attr;
02411
02412 if (packet->length + len > RADIUS_BUFFER_SIZE)
02413 {
02414
02415
02416
02417
02418
02419
02420 elog(WARNING,
02421 "Adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
02422 type, len);
02423 return;
02424
02425 }
02426
02427 attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
02428 attr->attribute = type;
02429 attr->length = len + 2;
02430 memcpy(attr->data, data, len);
02431 packet->length += attr->length;
02432 }
02433
02434 static int
02435 CheckRADIUSAuth(Port *port)
02436 {
02437 char *passwd;
02438 char *identifier = "postgresql";
02439 char radius_buffer[RADIUS_BUFFER_SIZE];
02440 char receive_buffer[RADIUS_BUFFER_SIZE];
02441 radius_packet *packet = (radius_packet *) radius_buffer;
02442 radius_packet *receivepacket = (radius_packet *) receive_buffer;
02443 int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
02444 uint8 *cryptvector;
02445 uint8 encryptedpassword[RADIUS_VECTOR_LENGTH];
02446 int packetlength;
02447 pgsocket sock;
02448
02449 #ifdef HAVE_IPV6
02450 struct sockaddr_in6 localaddr;
02451 struct sockaddr_in6 remoteaddr;
02452 #else
02453 struct sockaddr_in localaddr;
02454 struct sockaddr_in remoteaddr;
02455 #endif
02456 struct addrinfo hint;
02457 struct addrinfo *serveraddrs;
02458 char portstr[128];
02459 ACCEPT_TYPE_ARG3 addrsize;
02460 fd_set fdset;
02461 struct timeval endtime;
02462 int i,
02463 r;
02464
02465
02466 Assert(offsetof(radius_packet, vector) == 4);
02467
02468
02469 if (!port->hba->radiusserver || port->hba->radiusserver[0] == '\0')
02470 {
02471 ereport(LOG,
02472 (errmsg("RADIUS server not specified")));
02473 return STATUS_ERROR;
02474 }
02475
02476 if (!port->hba->radiussecret || port->hba->radiussecret[0] == '\0')
02477 {
02478 ereport(LOG,
02479 (errmsg("RADIUS secret not specified")));
02480 return STATUS_ERROR;
02481 }
02482
02483 if (port->hba->radiusport == 0)
02484 port->hba->radiusport = 1812;
02485
02486 MemSet(&hint, 0, sizeof(hint));
02487 hint.ai_socktype = SOCK_DGRAM;
02488 hint.ai_family = AF_UNSPEC;
02489 snprintf(portstr, sizeof(portstr), "%d", port->hba->radiusport);
02490
02491 r = pg_getaddrinfo_all(port->hba->radiusserver, portstr, &hint, &serveraddrs);
02492 if (r || !serveraddrs)
02493 {
02494 ereport(LOG,
02495 (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
02496 port->hba->radiusserver, gai_strerror(r))));
02497 if (serveraddrs)
02498 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
02499 return STATUS_ERROR;
02500 }
02501
02502
02503 if (port->hba->radiusidentifier && port->hba->radiusidentifier[0])
02504 identifier = port->hba->radiusidentifier;
02505
02506
02507 sendAuthRequest(port, AUTH_REQ_PASSWORD);
02508
02509 passwd = recv_password_packet(port);
02510 if (passwd == NULL)
02511 return STATUS_EOF;
02512
02513 if (strlen(passwd) == 0)
02514 {
02515 ereport(LOG,
02516 (errmsg("empty password returned by client")));
02517 return STATUS_ERROR;
02518 }
02519
02520 if (strlen(passwd) > RADIUS_VECTOR_LENGTH)
02521 {
02522 ereport(LOG,
02523 (errmsg("RADIUS authentication does not support passwords longer than 16 characters")));
02524 return STATUS_ERROR;
02525 }
02526
02527
02528 packet->code = RADIUS_ACCESS_REQUEST;
02529 packet->length = RADIUS_HEADER_LENGTH;
02530 #ifdef USE_SSL
02531 if (RAND_bytes(packet->vector, RADIUS_VECTOR_LENGTH) != 1)
02532 {
02533 ereport(LOG,
02534 (errmsg("could not generate random encryption vector")));
02535 return STATUS_ERROR;
02536 }
02537 #else
02538 for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
02539
02540 packet->vector[i] = random() % 255;
02541 #endif
02542 packet->id = packet->vector[0];
02543 radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (unsigned char *) &service, sizeof(service));
02544 radius_add_attribute(packet, RADIUS_USER_NAME, (unsigned char *) port->user_name, strlen(port->user_name));
02545 radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *) identifier, strlen(identifier));
02546
02547
02548
02549
02550
02551 cryptvector = palloc(RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret));
02552 memcpy(cryptvector, port->hba->radiussecret, strlen(port->hba->radiussecret));
02553 memcpy(cryptvector + strlen(port->hba->radiussecret), packet->vector, RADIUS_VECTOR_LENGTH);
02554 if (!pg_md5_binary(cryptvector, RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret), encryptedpassword))
02555 {
02556 ereport(LOG,
02557 (errmsg("could not perform MD5 encryption of password")));
02558 pfree(cryptvector);
02559 return STATUS_ERROR;
02560 }
02561 pfree(cryptvector);
02562 for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
02563 {
02564 if (i < strlen(passwd))
02565 encryptedpassword[i] = passwd[i] ^ encryptedpassword[i];
02566 else
02567 encryptedpassword[i] = '\0' ^ encryptedpassword[i];
02568 }
02569 radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, RADIUS_VECTOR_LENGTH);
02570
02571
02572 packetlength = packet->length;
02573 packet->length = htons(packet->length);
02574
02575 sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
02576 if (sock < 0)
02577 {
02578 ereport(LOG,
02579 (errmsg("could not create RADIUS socket: %m")));
02580 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
02581 return STATUS_ERROR;
02582 }
02583
02584 memset(&localaddr, 0, sizeof(localaddr));
02585 #ifdef HAVE_IPV6
02586 localaddr.sin6_family = serveraddrs[0].ai_family;
02587 localaddr.sin6_addr = in6addr_any;
02588 if (localaddr.sin6_family == AF_INET6)
02589 addrsize = sizeof(struct sockaddr_in6);
02590 else
02591 addrsize = sizeof(struct sockaddr_in);
02592 #else
02593 localaddr.sin_family = serveraddrs[0].ai_family;
02594 localaddr.sin_addr.s_addr = INADDR_ANY;
02595 addrsize = sizeof(struct sockaddr_in);
02596 #endif
02597 if (bind(sock, (struct sockaddr *) & localaddr, addrsize))
02598 {
02599 ereport(LOG,
02600 (errmsg("could not bind local RADIUS socket: %m")));
02601 closesocket(sock);
02602 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
02603 return STATUS_ERROR;
02604 }
02605
02606 if (sendto(sock, radius_buffer, packetlength, 0,
02607 serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
02608 {
02609 ereport(LOG,
02610 (errmsg("could not send RADIUS packet: %m")));
02611 closesocket(sock);
02612 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
02613 return STATUS_ERROR;
02614 }
02615
02616
02617 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
02618
02619
02620
02621
02622
02623
02624
02625 gettimeofday(&endtime, NULL);
02626 endtime.tv_sec += RADIUS_TIMEOUT;
02627
02628 while (true)
02629 {
02630 struct timeval timeout;
02631 struct timeval now;
02632 int64 timeoutval;
02633
02634 gettimeofday(&now, NULL);
02635 timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
02636 if (timeoutval <= 0)
02637 {
02638 ereport(LOG,
02639 (errmsg("timeout waiting for RADIUS response")));
02640 closesocket(sock);
02641 return STATUS_ERROR;
02642 }
02643 timeout.tv_sec = timeoutval / 1000000;
02644 timeout.tv_usec = timeoutval % 1000000;
02645
02646 FD_ZERO(&fdset);
02647 FD_SET(sock, &fdset);
02648
02649 r = select(sock + 1, &fdset, NULL, NULL, &timeout);
02650 if (r < 0)
02651 {
02652 if (errno == EINTR)
02653 continue;
02654
02655
02656 ereport(LOG,
02657 (errmsg("could not check status on RADIUS socket: %m")));
02658 closesocket(sock);
02659 return STATUS_ERROR;
02660 }
02661 if (r == 0)
02662 {
02663 ereport(LOG,
02664 (errmsg("timeout waiting for RADIUS response")));
02665 closesocket(sock);
02666 return STATUS_ERROR;
02667 }
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680 addrsize = sizeof(remoteaddr);
02681 packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
02682 (struct sockaddr *) & remoteaddr, &addrsize);
02683 if (packetlength < 0)
02684 {
02685 ereport(LOG,
02686 (errmsg("could not read RADIUS response: %m")));
02687 return STATUS_ERROR;
02688 }
02689
02690 #ifdef HAVE_IPV6
02691 if (remoteaddr.sin6_port != htons(port->hba->radiusport))
02692 #else
02693 if (remoteaddr.sin_port != htons(port->hba->radiusport))
02694 #endif
02695 {
02696 #ifdef HAVE_IPV6
02697 ereport(LOG,
02698 (errmsg("RADIUS response was sent from incorrect port: %d",
02699 ntohs(remoteaddr.sin6_port))));
02700 #else
02701 ereport(LOG,
02702 (errmsg("RADIUS response was sent from incorrect port: %d",
02703 ntohs(remoteaddr.sin_port))));
02704 #endif
02705 continue;
02706 }
02707
02708 if (packetlength < RADIUS_HEADER_LENGTH)
02709 {
02710 ereport(LOG,
02711 (errmsg("RADIUS response too short: %d", packetlength)));
02712 continue;
02713 }
02714
02715 if (packetlength != ntohs(receivepacket->length))
02716 {
02717 ereport(LOG,
02718 (errmsg("RADIUS response has corrupt length: %d (actual length %d)",
02719 ntohs(receivepacket->length), packetlength)));
02720 continue;
02721 }
02722
02723 if (packet->id != receivepacket->id)
02724 {
02725 ereport(LOG,
02726 (errmsg("RADIUS response is to a different request: %d (should be %d)",
02727 receivepacket->id, packet->id)));
02728 continue;
02729 }
02730
02731
02732
02733
02734
02735 cryptvector = palloc(packetlength + strlen(port->hba->radiussecret));
02736
02737 memcpy(cryptvector, receivepacket, 4);
02738 memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH);
02739
02740
02741 if (packetlength > RADIUS_HEADER_LENGTH)
02742
02743 memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
02744 memcpy(cryptvector + packetlength, port->hba->radiussecret, strlen(port->hba->radiussecret));
02745
02746 if (!pg_md5_binary(cryptvector,
02747 packetlength + strlen(port->hba->radiussecret),
02748 encryptedpassword))
02749 {
02750 ereport(LOG,
02751 (errmsg("could not perform MD5 encryption of received packet")));
02752 pfree(cryptvector);
02753 continue;
02754 }
02755 pfree(cryptvector);
02756
02757 if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
02758 {
02759 ereport(LOG,
02760 (errmsg("RADIUS response has incorrect MD5 signature")));
02761 continue;
02762 }
02763
02764 if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
02765 {
02766 closesocket(sock);
02767 return STATUS_OK;
02768 }
02769 else if (receivepacket->code == RADIUS_ACCESS_REJECT)
02770 {
02771 closesocket(sock);
02772 return STATUS_ERROR;
02773 }
02774 else
02775 {
02776 ereport(LOG,
02777 (errmsg("RADIUS response has invalid code (%d) for user \"%s\"",
02778 receivepacket->code, port->user_name)));
02779 continue;
02780 }
02781 }
02782 }