00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres_fe.h"
00017
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <fcntl.h>
00021 #include <ctype.h>
00022 #include <time.h>
00023 #include <unistd.h>
00024
00025 #include "libpq-fe.h"
00026 #include "libpq-int.h"
00027 #include "fe-auth.h"
00028 #include "pg_config_paths.h"
00029
00030 #ifdef WIN32
00031 #include "win32.h"
00032 #ifdef _WIN32_IE
00033 #undef _WIN32_IE
00034 #endif
00035 #define _WIN32_IE 0x0500
00036 #ifdef near
00037 #undef near
00038 #endif
00039 #define near
00040 #include <shlobj.h>
00041 #ifdef WIN32_ONLY_COMPILER
00042 #include <mstcpip.h>
00043 #endif
00044 #else
00045 #include <sys/socket.h>
00046 #include <netdb.h>
00047 #include <netinet/in.h>
00048 #ifdef HAVE_NETINET_TCP_H
00049 #include <netinet/tcp.h>
00050 #endif
00051 #include <arpa/inet.h>
00052 #endif
00053
00054 #ifdef ENABLE_THREAD_SAFETY
00055 #ifdef WIN32
00056 #include "pthread-win32.h"
00057 #else
00058 #include <pthread.h>
00059 #endif
00060 #endif
00061
00062 #ifdef USE_LDAP
00063 #ifdef WIN32
00064 #include <winldap.h>
00065 #else
00066
00067 #define LDAP_DEPRECATED 1
00068 #include <ldap.h>
00069 typedef struct timeval LDAP_TIMEVAL;
00070 #endif
00071 static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
00072 PQExpBuffer errorMessage);
00073 #endif
00074
00075 #include "libpq/ip.h"
00076 #include "mb/pg_wchar.h"
00077
00078 #ifndef FD_CLOEXEC
00079 #define FD_CLOEXEC 1
00080 #endif
00081
00082
00083 #ifndef WIN32
00084 #define PGPASSFILE ".pgpass"
00085 #else
00086 #define PGPASSFILE "pgpass.conf"
00087 #endif
00088
00089
00090
00091
00092
00093
00094
00095 #define ERRCODE_APPNAME_UNKNOWN "42704"
00096
00097
00098 #define ERRCODE_INVALID_PASSWORD "28P01"
00099
00100 #define ERRCODE_CANNOT_CONNECT_NOW "57P03"
00101
00102
00103
00104
00105
00106 #define DefaultHost "localhost"
00107 #define DefaultTty ""
00108 #define DefaultOption ""
00109 #define DefaultAuthtype ""
00110 #define DefaultPassword ""
00111 #ifdef USE_SSL
00112 #define DefaultSSLMode "prefer"
00113 #else
00114 #define DefaultSSLMode "disable"
00115 #endif
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 typedef struct _internalPQconninfoOption
00146 {
00147 char *keyword;
00148 char *envvar;
00149 char *compiled;
00150 char *val;
00151 char *label;
00152 char *dispchar;
00153
00154
00155
00156
00157 int dispsize;
00158
00159
00160
00161
00162
00163
00164 off_t connofs;
00165 } internalPQconninfoOption;
00166
00167 static const internalPQconninfoOption PQconninfoOptions[] = {
00168
00169
00170
00171
00172
00173 {"authtype", "PGAUTHTYPE", DefaultAuthtype, NULL,
00174 "Database-Authtype", "D", 20, -1},
00175
00176 {"service", "PGSERVICE", NULL, NULL,
00177 "Database-Service", "", 20, -1},
00178
00179 {"user", "PGUSER", NULL, NULL,
00180 "Database-User", "", 20,
00181 offsetof(struct pg_conn, pguser)},
00182
00183 {"password", "PGPASSWORD", NULL, NULL,
00184 "Database-Password", "*", 20,
00185 offsetof(struct pg_conn, pgpass)},
00186
00187 {"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
00188 "Connect-timeout", "", 10,
00189 offsetof(struct pg_conn, connect_timeout)},
00190
00191 {"dbname", "PGDATABASE", NULL, NULL,
00192 "Database-Name", "", 20,
00193 offsetof(struct pg_conn, dbName)},
00194
00195 {"host", "PGHOST", NULL, NULL,
00196 "Database-Host", "", 40,
00197 offsetof(struct pg_conn, pghost)},
00198
00199 {"hostaddr", "PGHOSTADDR", NULL, NULL,
00200 "Database-Host-IP-Address", "", 45,
00201 offsetof(struct pg_conn, pghostaddr)},
00202
00203 {"port", "PGPORT", DEF_PGPORT_STR, NULL,
00204 "Database-Port", "", 6,
00205 offsetof(struct pg_conn, pgport)},
00206
00207 {"client_encoding", "PGCLIENTENCODING", NULL, NULL,
00208 "Client-Encoding", "", 10,
00209 offsetof(struct pg_conn, client_encoding_initial)},
00210
00211
00212
00213
00214
00215 {"tty", "PGTTY", DefaultTty, NULL,
00216 "Backend-Debug-TTY", "D", 40,
00217 offsetof(struct pg_conn, pgtty)},
00218
00219 {"options", "PGOPTIONS", DefaultOption, NULL,
00220 "Backend-Debug-Options", "D", 40,
00221 offsetof(struct pg_conn, pgoptions)},
00222
00223 {"application_name", "PGAPPNAME", NULL, NULL,
00224 "Application-Name", "", 64,
00225 offsetof(struct pg_conn, appname)},
00226
00227 {"fallback_application_name", NULL, NULL, NULL,
00228 "Fallback-Application-Name", "", 64,
00229 offsetof(struct pg_conn, fbappname)},
00230
00231 {"keepalives", NULL, NULL, NULL,
00232 "TCP-Keepalives", "", 1,
00233 offsetof(struct pg_conn, keepalives)},
00234
00235 {"keepalives_idle", NULL, NULL, NULL,
00236 "TCP-Keepalives-Idle", "", 10,
00237 offsetof(struct pg_conn, keepalives_idle)},
00238
00239 {"keepalives_interval", NULL, NULL, NULL,
00240 "TCP-Keepalives-Interval", "", 10,
00241 offsetof(struct pg_conn, keepalives_interval)},
00242
00243 {"keepalives_count", NULL, NULL, NULL,
00244 "TCP-Keepalives-Count", "", 10,
00245 offsetof(struct pg_conn, keepalives_count)},
00246
00247
00248
00249
00250
00251
00252
00253 {"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
00254 "SSL-Mode", "", 8,
00255 offsetof(struct pg_conn, sslmode)},
00256
00257 {"sslcompression", "PGSSLCOMPRESSION", "1", NULL,
00258 "SSL-Compression", "", 1,
00259 offsetof(struct pg_conn, sslcompression)},
00260
00261 {"sslcert", "PGSSLCERT", NULL, NULL,
00262 "SSL-Client-Cert", "", 64,
00263 offsetof(struct pg_conn, sslcert)},
00264
00265 {"sslkey", "PGSSLKEY", NULL, NULL,
00266 "SSL-Client-Key", "", 64,
00267 offsetof(struct pg_conn, sslkey)},
00268
00269 {"sslrootcert", "PGSSLROOTCERT", NULL, NULL,
00270 "SSL-Root-Certificate", "", 64,
00271 offsetof(struct pg_conn, sslrootcert)},
00272
00273 {"sslcrl", "PGSSLCRL", NULL, NULL,
00274 "SSL-Revocation-List", "", 64,
00275 offsetof(struct pg_conn, sslcrl)},
00276
00277 {"requirepeer", "PGREQUIREPEER", NULL, NULL,
00278 "Require-Peer", "", 10,
00279 offsetof(struct pg_conn, requirepeer)},
00280
00281 #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
00282
00283 {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
00284 "Kerberos-service-name", "", 20,
00285 offsetof(struct pg_conn, krbsrvname)},
00286 #endif
00287
00288 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
00289
00290
00291
00292
00293
00294 {"gsslib", "PGGSSLIB", NULL, NULL,
00295 "GSS-library", "", 7,
00296 offsetof(struct pg_conn, gsslib)},
00297 #endif
00298
00299 {"replication", NULL, NULL, NULL,
00300 "Replication", "D", 5,
00301 offsetof(struct pg_conn, replication)},
00302
00303
00304 {NULL, NULL, NULL, NULL,
00305 NULL, NULL, 0}
00306 };
00307
00308 static const PQEnvironmentOption EnvironmentOptions[] =
00309 {
00310
00311 {
00312 "PGDATESTYLE", "datestyle"
00313 },
00314 {
00315 "PGTZ", "timezone"
00316 },
00317
00318 {
00319 "PGGEQO", "geqo"
00320 },
00321 {
00322 NULL, NULL
00323 }
00324 };
00325
00326
00327 static const char uri_designator[] = "postgresql://";
00328 static const char short_uri_designator[] = "postgres://";
00329
00330 static bool connectOptions1(PGconn *conn, const char *conninfo);
00331 static bool connectOptions2(PGconn *conn);
00332 static int connectDBStart(PGconn *conn);
00333 static int connectDBComplete(PGconn *conn);
00334 static PGPing internal_ping(PGconn *conn);
00335 static PGconn *makeEmptyPGconn(void);
00336 static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
00337 static void freePGconn(PGconn *conn);
00338 static void closePGconn(PGconn *conn);
00339 static PQconninfoOption *conninfo_init(PQExpBuffer errorMessage);
00340 static PQconninfoOption *parse_connection_string(const char *conninfo,
00341 PQExpBuffer errorMessage, bool use_defaults);
00342 static int uri_prefix_length(const char *connstr);
00343 static bool recognized_connection_string(const char *connstr);
00344 static PQconninfoOption *conninfo_parse(const char *conninfo,
00345 PQExpBuffer errorMessage, bool use_defaults);
00346 static PQconninfoOption *conninfo_array_parse(const char *const * keywords,
00347 const char *const * values, PQExpBuffer errorMessage,
00348 bool use_defaults, int expand_dbname);
00349 static bool conninfo_add_defaults(PQconninfoOption *options,
00350 PQExpBuffer errorMessage);
00351 static PQconninfoOption *conninfo_uri_parse(const char *uri,
00352 PQExpBuffer errorMessage, bool use_defaults);
00353 static bool conninfo_uri_parse_options(PQconninfoOption *options,
00354 const char *uri, PQExpBuffer errorMessage);
00355 static bool conninfo_uri_parse_params(char *params,
00356 PQconninfoOption *connOptions,
00357 PQExpBuffer errorMessage);
00358 static char *conninfo_uri_decode(const char *str, PQExpBuffer errorMessage);
00359 static bool get_hexdigit(char digit, int *value);
00360 static const char *conninfo_getval(PQconninfoOption *connOptions,
00361 const char *keyword);
00362 static PQconninfoOption *conninfo_storeval(PQconninfoOption *connOptions,
00363 const char *keyword, const char *value,
00364 PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode);
00365 static PQconninfoOption *conninfo_find(PQconninfoOption *connOptions,
00366 const char *keyword);
00367 static void defaultNoticeReceiver(void *arg, const PGresult *res);
00368 static void defaultNoticeProcessor(void *arg, const char *message);
00369 static int parseServiceInfo(PQconninfoOption *options,
00370 PQExpBuffer errorMessage);
00371 static int parseServiceFile(const char *serviceFile,
00372 const char *service,
00373 PQconninfoOption *options,
00374 PQExpBuffer errorMessage,
00375 bool *group_found);
00376 static char *pwdfMatchesString(char *buf, char *token);
00377 static char *PasswordFromFile(char *hostname, char *port, char *dbname,
00378 char *username);
00379 static bool getPgPassFilename(char *pgpassfile);
00380 static void dot_pg_pass_warning(PGconn *conn);
00381 static void default_threadlock(int acquire);
00382
00383
00384
00385 pgthreadlock_t pg_g_threadlock = default_threadlock;
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 void
00396 pqDropConnection(PGconn *conn)
00397 {
00398
00399 pqsecure_close(conn);
00400
00401 if (conn->sock >= 0)
00402 closesocket(conn->sock);
00403 conn->sock = -1;
00404
00405 conn->inStart = conn->inCursor = conn->inEnd = 0;
00406 conn->outCount = 0;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 PGconn *
00455 PQconnectdbParams(const char *const * keywords,
00456 const char *const * values,
00457 int expand_dbname)
00458 {
00459 PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
00460
00461 if (conn && conn->status != CONNECTION_BAD)
00462 (void) connectDBComplete(conn);
00463
00464 return conn;
00465
00466 }
00467
00468
00469
00470
00471
00472
00473 PGPing
00474 PQpingParams(const char *const * keywords,
00475 const char *const * values,
00476 int expand_dbname)
00477 {
00478 PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
00479 PGPing ret;
00480
00481 ret = internal_ping(conn);
00482 PQfinish(conn);
00483
00484 return ret;
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 PGconn *
00511 PQconnectdb(const char *conninfo)
00512 {
00513 PGconn *conn = PQconnectStart(conninfo);
00514
00515 if (conn && conn->status != CONNECTION_BAD)
00516 (void) connectDBComplete(conn);
00517
00518 return conn;
00519 }
00520
00521
00522
00523
00524
00525
00526 PGPing
00527 PQping(const char *conninfo)
00528 {
00529 PGconn *conn = PQconnectStart(conninfo);
00530 PGPing ret;
00531
00532 ret = internal_ping(conn);
00533 PQfinish(conn);
00534
00535 return ret;
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 PGconn *
00558 PQconnectStartParams(const char *const * keywords,
00559 const char *const * values,
00560 int expand_dbname)
00561 {
00562 PGconn *conn;
00563 PQconninfoOption *connOptions;
00564
00565
00566
00567
00568 conn = makeEmptyPGconn();
00569 if (conn == NULL)
00570 return NULL;
00571
00572
00573
00574
00575 connOptions = conninfo_array_parse(keywords, values,
00576 &conn->errorMessage,
00577 true, expand_dbname);
00578 if (connOptions == NULL)
00579 {
00580 conn->status = CONNECTION_BAD;
00581
00582 return conn;
00583 }
00584
00585
00586
00587
00588 fillPGconn(conn, connOptions);
00589
00590
00591
00592
00593 PQconninfoFree(connOptions);
00594
00595
00596
00597
00598 if (!connectOptions2(conn))
00599 return conn;
00600
00601
00602
00603
00604 if (!connectDBStart(conn))
00605 {
00606
00607 conn->status = CONNECTION_BAD;
00608 }
00609
00610 return conn;
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 PGconn *
00633 PQconnectStart(const char *conninfo)
00634 {
00635 PGconn *conn;
00636
00637
00638
00639
00640 conn = makeEmptyPGconn();
00641 if (conn == NULL)
00642 return NULL;
00643
00644
00645
00646
00647 if (!connectOptions1(conn, conninfo))
00648 return conn;
00649
00650
00651
00652
00653 if (!connectOptions2(conn))
00654 return conn;
00655
00656
00657
00658
00659 if (!connectDBStart(conn))
00660 {
00661
00662 conn->status = CONNECTION_BAD;
00663 }
00664
00665 return conn;
00666 }
00667
00668 static void
00669 fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
00670 {
00671 const internalPQconninfoOption *option;
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 for (option = PQconninfoOptions; option->keyword; option++)
00682 {
00683 const char *tmp = conninfo_getval(connOptions, option->keyword);
00684
00685 if (tmp && option->connofs >= 0)
00686 {
00687 char **connmember = (char **) ((char *) conn + option->connofs);
00688
00689 if (*connmember)
00690 free(*connmember);
00691 *connmember = tmp ? strdup(tmp) : NULL;
00692 }
00693 }
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 static bool
00708 connectOptions1(PGconn *conn, const char *conninfo)
00709 {
00710 PQconninfoOption *connOptions;
00711
00712
00713
00714
00715 connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
00716 if (connOptions == NULL)
00717 {
00718 conn->status = CONNECTION_BAD;
00719
00720 return false;
00721 }
00722
00723
00724
00725
00726 fillPGconn(conn, connOptions);
00727
00728
00729
00730
00731 PQconninfoFree(connOptions);
00732
00733 return true;
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 static bool
00745 connectOptions2(PGconn *conn)
00746 {
00747
00748
00749
00750 if ((conn->dbName == NULL || conn->dbName[0] == '\0')
00751 && conn->pguser != NULL)
00752 {
00753 if (conn->dbName)
00754 free(conn->dbName);
00755 conn->dbName = strdup(conn->pguser);
00756 }
00757
00758
00759
00760
00761 if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
00762 {
00763 if (conn->pgpass)
00764 free(conn->pgpass);
00765 conn->pgpass = PasswordFromFile(conn->pghost, conn->pgport,
00766 conn->dbName, conn->pguser);
00767 if (conn->pgpass == NULL)
00768 conn->pgpass = strdup(DefaultPassword);
00769 else
00770 conn->dot_pgpass_used = true;
00771 }
00772
00773
00774
00775
00776 if (conn->pghost && is_absolute_path(conn->pghost))
00777 {
00778 if (conn->pgunixsocket)
00779 free(conn->pgunixsocket);
00780 conn->pgunixsocket = conn->pghost;
00781 conn->pghost = NULL;
00782 }
00783
00784
00785
00786
00787 if (conn->sslmode)
00788 {
00789 if (strcmp(conn->sslmode, "disable") != 0
00790 && strcmp(conn->sslmode, "allow") != 0
00791 && strcmp(conn->sslmode, "prefer") != 0
00792 && strcmp(conn->sslmode, "require") != 0
00793 && strcmp(conn->sslmode, "verify-ca") != 0
00794 && strcmp(conn->sslmode, "verify-full") != 0)
00795 {
00796 conn->status = CONNECTION_BAD;
00797 printfPQExpBuffer(&conn->errorMessage,
00798 libpq_gettext("invalid sslmode value: \"%s\"\n"),
00799 conn->sslmode);
00800 return false;
00801 }
00802
00803 #ifndef USE_SSL
00804 switch (conn->sslmode[0])
00805 {
00806 case 'a':
00807 case 'p':
00808
00809
00810
00811
00812
00813 break;
00814
00815 case 'r':
00816 case 'v':
00817 conn->status = CONNECTION_BAD;
00818 printfPQExpBuffer(&conn->errorMessage,
00819 libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
00820 conn->sslmode);
00821 return false;
00822 }
00823 #endif
00824 }
00825 else
00826 conn->sslmode = strdup(DefaultSSLMode);
00827
00828
00829
00830
00831 if (conn->client_encoding_initial &&
00832 strcmp(conn->client_encoding_initial, "auto") == 0)
00833 {
00834 free(conn->client_encoding_initial);
00835 conn->client_encoding_initial = strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)));
00836 }
00837
00838
00839
00840
00841
00842
00843 conn->options_valid = true;
00844
00845 return true;
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864 PQconninfoOption *
00865 PQconndefaults(void)
00866 {
00867 PQExpBufferData errorBuf;
00868 PQconninfoOption *connOptions;
00869
00870
00871 initPQExpBuffer(&errorBuf);
00872 if (PQExpBufferDataBroken(errorBuf))
00873 return NULL;
00874
00875 connOptions = conninfo_init(&errorBuf);
00876 if (connOptions != NULL)
00877 {
00878 if (!conninfo_add_defaults(connOptions, &errorBuf))
00879 {
00880 PQconninfoFree(connOptions);
00881 connOptions = NULL;
00882 }
00883 }
00884
00885 termPQExpBuffer(&errorBuf);
00886 return connOptions;
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901 PGconn *
00902 PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
00903 const char *pgtty, const char *dbName, const char *login,
00904 const char *pwd)
00905 {
00906 PGconn *conn;
00907
00908
00909
00910
00911 conn = makeEmptyPGconn();
00912 if (conn == NULL)
00913 return NULL;
00914
00915
00916
00917
00918
00919 if (dbName && recognized_connection_string(dbName))
00920 {
00921 if (!connectOptions1(conn, dbName))
00922 return conn;
00923 }
00924 else
00925 {
00926
00927
00928
00929
00930 if (!connectOptions1(conn, ""))
00931 return conn;
00932
00933
00934 if (dbName && dbName[0] != '\0')
00935 {
00936 if (conn->dbName)
00937 free(conn->dbName);
00938 conn->dbName = strdup(dbName);
00939 }
00940 }
00941
00942
00943
00944
00945
00946 if (pghost && pghost[0] != '\0')
00947 {
00948 if (conn->pghost)
00949 free(conn->pghost);
00950 conn->pghost = strdup(pghost);
00951 }
00952
00953 if (pgport && pgport[0] != '\0')
00954 {
00955 if (conn->pgport)
00956 free(conn->pgport);
00957 conn->pgport = strdup(pgport);
00958 }
00959
00960 if (pgoptions && pgoptions[0] != '\0')
00961 {
00962 if (conn->pgoptions)
00963 free(conn->pgoptions);
00964 conn->pgoptions = strdup(pgoptions);
00965 }
00966
00967 if (pgtty && pgtty[0] != '\0')
00968 {
00969 if (conn->pgtty)
00970 free(conn->pgtty);
00971 conn->pgtty = strdup(pgtty);
00972 }
00973
00974 if (login && login[0] != '\0')
00975 {
00976 if (conn->pguser)
00977 free(conn->pguser);
00978 conn->pguser = strdup(login);
00979 }
00980
00981 if (pwd && pwd[0] != '\0')
00982 {
00983 if (conn->pgpass)
00984 free(conn->pgpass);
00985 conn->pgpass = strdup(pwd);
00986 }
00987
00988
00989
00990
00991 if (!connectOptions2(conn))
00992 return conn;
00993
00994
00995
00996
00997 if (connectDBStart(conn))
00998 (void) connectDBComplete(conn);
00999
01000 return conn;
01001 }
01002
01003
01004
01005
01006
01007
01008
01009
01010 static int
01011 connectNoDelay(PGconn *conn)
01012 {
01013 #ifdef TCP_NODELAY
01014 int on = 1;
01015
01016 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
01017 (char *) &on,
01018 sizeof(on)) < 0)
01019 {
01020 char sebuf[256];
01021
01022 appendPQExpBuffer(&conn->errorMessage,
01023 libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
01024 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01025 return 0;
01026 }
01027 #endif
01028
01029 return 1;
01030 }
01031
01032
01033
01034
01035
01036
01037
01038 static void
01039 connectFailureMessage(PGconn *conn, int errorno)
01040 {
01041 char sebuf[256];
01042
01043 #ifdef HAVE_UNIX_SOCKETS
01044 if (IS_AF_UNIX(conn->raddr.addr.ss_family))
01045 {
01046 char service[NI_MAXHOST];
01047
01048 pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
01049 NULL, 0,
01050 service, sizeof(service),
01051 NI_NUMERICSERV);
01052 appendPQExpBuffer(&conn->errorMessage,
01053 libpq_gettext("could not connect to server: %s\n"
01054 "\tIs the server running locally and accepting\n"
01055 "\tconnections on Unix domain socket \"%s\"?\n"),
01056 SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
01057 service);
01058 }
01059 else
01060 #endif
01061 {
01062 char host_addr[NI_MAXHOST];
01063 const char *displayed_host;
01064 struct sockaddr_storage *addr = &conn->raddr.addr;
01065
01066
01067
01068
01069
01070 if (conn->pghostaddr != NULL)
01071 strlcpy(host_addr, conn->pghostaddr, NI_MAXHOST);
01072 else if (addr->ss_family == AF_INET)
01073 {
01074 if (inet_net_ntop(AF_INET,
01075 &((struct sockaddr_in *) addr)->sin_addr.s_addr,
01076 32,
01077 host_addr, sizeof(host_addr)) == NULL)
01078 strcpy(host_addr, "???");
01079 }
01080 #ifdef HAVE_IPV6
01081 else if (addr->ss_family == AF_INET6)
01082 {
01083 if (inet_net_ntop(AF_INET6,
01084 &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
01085 128,
01086 host_addr, sizeof(host_addr)) == NULL)
01087 strcpy(host_addr, "???");
01088 }
01089 #endif
01090 else
01091 strcpy(host_addr, "???");
01092
01093 if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
01094 displayed_host = conn->pghostaddr;
01095 else if (conn->pghost && conn->pghost[0] != '\0')
01096 displayed_host = conn->pghost;
01097 else
01098 displayed_host = DefaultHost;
01099
01100
01101
01102
01103
01104
01105 if ((conn->pghostaddr == NULL) &&
01106 (conn->pghost == NULL || strcmp(conn->pghost, host_addr) != 0))
01107 appendPQExpBuffer(&conn->errorMessage,
01108 libpq_gettext("could not connect to server: %s\n"
01109 "\tIs the server running on host \"%s\" (%s) and accepting\n"
01110 "\tTCP/IP connections on port %s?\n"),
01111 SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
01112 displayed_host,
01113 host_addr,
01114 conn->pgport);
01115 else
01116 appendPQExpBuffer(&conn->errorMessage,
01117 libpq_gettext("could not connect to server: %s\n"
01118 "\tIs the server running on host \"%s\" and accepting\n"
01119 "\tTCP/IP connections on port %s?\n"),
01120 SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
01121 displayed_host,
01122 conn->pgport);
01123 }
01124 }
01125
01126
01127
01128
01129
01130
01131 static int
01132 useKeepalives(PGconn *conn)
01133 {
01134 char *ep;
01135 int val;
01136
01137 if (conn->keepalives == NULL)
01138 return 1;
01139 val = strtol(conn->keepalives, &ep, 10);
01140 if (*ep)
01141 return -1;
01142 return val != 0 ? 1 : 0;
01143 }
01144
01145 #ifndef WIN32
01146
01147
01148
01149 static int
01150 setKeepalivesIdle(PGconn *conn)
01151 {
01152 int idle;
01153
01154 if (conn->keepalives_idle == NULL)
01155 return 1;
01156
01157 idle = atoi(conn->keepalives_idle);
01158 if (idle < 0)
01159 idle = 0;
01160
01161 #ifdef TCP_KEEPIDLE
01162 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPIDLE,
01163 (char *) &idle, sizeof(idle)) < 0)
01164 {
01165 char sebuf[256];
01166
01167 appendPQExpBuffer(&conn->errorMessage,
01168 libpq_gettext("setsockopt(TCP_KEEPIDLE) failed: %s\n"),
01169 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01170 return 0;
01171 }
01172 #else
01173 #ifdef TCP_KEEPALIVE
01174
01175 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPALIVE,
01176 (char *) &idle, sizeof(idle)) < 0)
01177 {
01178 char sebuf[256];
01179
01180 appendPQExpBuffer(&conn->errorMessage,
01181 libpq_gettext("setsockopt(TCP_KEEPALIVE) failed: %s\n"),
01182 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01183 return 0;
01184 }
01185 #endif
01186 #endif
01187
01188 return 1;
01189 }
01190
01191
01192
01193
01194 static int
01195 setKeepalivesInterval(PGconn *conn)
01196 {
01197 int interval;
01198
01199 if (conn->keepalives_interval == NULL)
01200 return 1;
01201
01202 interval = atoi(conn->keepalives_interval);
01203 if (interval < 0)
01204 interval = 0;
01205
01206 #ifdef TCP_KEEPINTVL
01207 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL,
01208 (char *) &interval, sizeof(interval)) < 0)
01209 {
01210 char sebuf[256];
01211
01212 appendPQExpBuffer(&conn->errorMessage,
01213 libpq_gettext("setsockopt(TCP_KEEPINTVL) failed: %s\n"),
01214 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01215 return 0;
01216 }
01217 #endif
01218
01219 return 1;
01220 }
01221
01222
01223
01224
01225
01226 static int
01227 setKeepalivesCount(PGconn *conn)
01228 {
01229 int count;
01230
01231 if (conn->keepalives_count == NULL)
01232 return 1;
01233
01234 count = atoi(conn->keepalives_count);
01235 if (count < 0)
01236 count = 0;
01237
01238 #ifdef TCP_KEEPCNT
01239 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT,
01240 (char *) &count, sizeof(count)) < 0)
01241 {
01242 char sebuf[256];
01243
01244 appendPQExpBuffer(&conn->errorMessage,
01245 libpq_gettext("setsockopt(TCP_KEEPCNT) failed: %s\n"),
01246 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01247 return 0;
01248 }
01249 #endif
01250
01251 return 1;
01252 }
01253 #else
01254 #ifdef SIO_KEEPALIVE_VALS
01255
01256
01257
01258
01259 static int
01260 setKeepalivesWin32(PGconn *conn)
01261 {
01262 struct tcp_keepalive ka;
01263 DWORD retsize;
01264 int idle = 0;
01265 int interval = 0;
01266
01267 if (conn->keepalives_idle)
01268 idle = atoi(conn->keepalives_idle);
01269 if (idle <= 0)
01270 idle = 2 * 60 * 60;
01271
01272 if (conn->keepalives_interval)
01273 interval = atoi(conn->keepalives_interval);
01274 if (interval <= 0)
01275 interval = 1;
01276
01277 ka.onoff = 1;
01278 ka.keepalivetime = idle * 1000;
01279 ka.keepaliveinterval = interval * 1000;
01280
01281 if (WSAIoctl(conn->sock,
01282 SIO_KEEPALIVE_VALS,
01283 (LPVOID) &ka,
01284 sizeof(ka),
01285 NULL,
01286 0,
01287 &retsize,
01288 NULL,
01289 NULL)
01290 != 0)
01291 {
01292 appendPQExpBuffer(&conn->errorMessage,
01293 libpq_gettext("WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n"),
01294 WSAGetLastError());
01295 return 0;
01296 }
01297 return 1;
01298 }
01299 #endif
01300 #endif
01301
01302
01303
01304
01305
01306
01307
01308
01309 static int
01310 connectDBStart(PGconn *conn)
01311 {
01312 int portnum;
01313 char portstr[MAXPGPATH];
01314 struct addrinfo *addrs = NULL;
01315 struct addrinfo hint;
01316 const char *node;
01317 int ret;
01318
01319 if (!conn)
01320 return 0;
01321
01322 if (!conn->options_valid)
01323 goto connect_errReturn;
01324
01325
01326 conn->inStart = conn->inCursor = conn->inEnd = 0;
01327 conn->outCount = 0;
01328
01329
01330
01331
01332
01333
01334 MemSet(&hint, 0, sizeof(hint));
01335 hint.ai_socktype = SOCK_STREAM;
01336 hint.ai_family = AF_UNSPEC;
01337
01338
01339 if (conn->pgport != NULL && conn->pgport[0] != '\0')
01340 {
01341 portnum = atoi(conn->pgport);
01342 if (portnum < 1 || portnum > 65535)
01343 {
01344 appendPQExpBuffer(&conn->errorMessage,
01345 libpq_gettext("invalid port number: \"%s\"\n"),
01346 conn->pgport);
01347 conn->options_valid = false;
01348 goto connect_errReturn;
01349 }
01350 }
01351 else
01352 portnum = DEF_PGPORT;
01353 snprintf(portstr, sizeof(portstr), "%d", portnum);
01354
01355 if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
01356 {
01357
01358 node = conn->pghostaddr;
01359 hint.ai_family = AF_UNSPEC;
01360 hint.ai_flags = AI_NUMERICHOST;
01361 }
01362 else if (conn->pghost != NULL && conn->pghost[0] != '\0')
01363 {
01364
01365 node = conn->pghost;
01366 hint.ai_family = AF_UNSPEC;
01367 }
01368 else
01369 {
01370 #ifdef HAVE_UNIX_SOCKETS
01371
01372 node = NULL;
01373 hint.ai_family = AF_UNIX;
01374 UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket);
01375 if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
01376 {
01377 appendPQExpBuffer(&conn->errorMessage,
01378 libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
01379 portstr,
01380 (int) (UNIXSOCK_PATH_BUFLEN - 1));
01381 conn->options_valid = false;
01382 goto connect_errReturn;
01383 }
01384 #else
01385
01386 node = DefaultHost;
01387 hint.ai_family = AF_UNSPEC;
01388 #endif
01389 }
01390
01391
01392 ret = pg_getaddrinfo_all(node, portstr, &hint, &addrs);
01393 if (ret || !addrs)
01394 {
01395 if (node)
01396 appendPQExpBuffer(&conn->errorMessage,
01397 libpq_gettext("could not translate host name \"%s\" to address: %s\n"),
01398 node, gai_strerror(ret));
01399 else
01400 appendPQExpBuffer(&conn->errorMessage,
01401 libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"),
01402 portstr, gai_strerror(ret));
01403 if (addrs)
01404 pg_freeaddrinfo_all(hint.ai_family, addrs);
01405 conn->options_valid = false;
01406 goto connect_errReturn;
01407 }
01408
01409 #ifdef USE_SSL
01410
01411 if (conn->sslmode[0] == 'd')
01412 conn->allow_ssl_try = false;
01413 else if (conn->sslmode[0] == 'a')
01414 conn->wait_ssl_try = true;
01415 #endif
01416
01417
01418
01419
01420 conn->addrlist = addrs;
01421 conn->addr_cur = addrs;
01422 conn->addrlist_family = hint.ai_family;
01423 conn->pversion = PG_PROTOCOL(3, 0);
01424 conn->send_appname = true;
01425 conn->status = CONNECTION_NEEDED;
01426
01427
01428
01429
01430
01431
01432
01433
01434 if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
01435 return 1;
01436
01437 connect_errReturn:
01438 pqDropConnection(conn);
01439 conn->status = CONNECTION_BAD;
01440 return 0;
01441 }
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 static int
01452 connectDBComplete(PGconn *conn)
01453 {
01454 PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
01455 time_t finish_time = ((time_t) -1);
01456
01457 if (conn == NULL || conn->status == CONNECTION_BAD)
01458 return 0;
01459
01460
01461
01462
01463 if (conn->connect_timeout != NULL)
01464 {
01465 int timeout = atoi(conn->connect_timeout);
01466
01467 if (timeout > 0)
01468 {
01469
01470
01471
01472 if (timeout < 2)
01473 timeout = 2;
01474
01475 finish_time = time(NULL) + timeout;
01476 }
01477 }
01478
01479 for (;;)
01480 {
01481
01482
01483
01484
01485 switch (flag)
01486 {
01487 case PGRES_POLLING_OK:
01488
01489
01490
01491
01492
01493 resetPQExpBuffer(&conn->errorMessage);
01494 return 1;
01495
01496 case PGRES_POLLING_READING:
01497 if (pqWaitTimed(1, 0, conn, finish_time))
01498 {
01499 conn->status = CONNECTION_BAD;
01500 return 0;
01501 }
01502 break;
01503
01504 case PGRES_POLLING_WRITING:
01505 if (pqWaitTimed(0, 1, conn, finish_time))
01506 {
01507 conn->status = CONNECTION_BAD;
01508 return 0;
01509 }
01510 break;
01511
01512 default:
01513
01514 conn->status = CONNECTION_BAD;
01515 return 0;
01516 }
01517
01518
01519
01520
01521 flag = PQconnectPoll(conn);
01522 }
01523 }
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552 PostgresPollingStatusType
01553 PQconnectPoll(PGconn *conn)
01554 {
01555 PGresult *res;
01556 char sebuf[256];
01557 int optval;
01558
01559 if (conn == NULL)
01560 return PGRES_POLLING_FAILED;
01561
01562
01563 switch (conn->status)
01564 {
01565
01566
01567
01568
01569 case CONNECTION_BAD:
01570 return PGRES_POLLING_FAILED;
01571 case CONNECTION_OK:
01572 return PGRES_POLLING_OK;
01573
01574
01575 case CONNECTION_AWAITING_RESPONSE:
01576 case CONNECTION_AUTH_OK:
01577 {
01578
01579 int n = pqReadData(conn);
01580
01581 if (n < 0)
01582 goto error_return;
01583 if (n == 0)
01584 return PGRES_POLLING_READING;
01585
01586 break;
01587 }
01588
01589
01590 case CONNECTION_STARTED:
01591 case CONNECTION_MADE:
01592 break;
01593
01594
01595 case CONNECTION_SETENV:
01596 break;
01597
01598
01599 case CONNECTION_SSL_STARTUP:
01600 case CONNECTION_NEEDED:
01601 break;
01602
01603 default:
01604 appendPQExpBuffer(&conn->errorMessage,
01605 libpq_gettext(
01606 "invalid connection state, "
01607 "probably indicative of memory corruption\n"
01608 ));
01609 goto error_return;
01610 }
01611
01612
01613 keep_going:
01614
01615 switch (conn->status)
01616 {
01617 case CONNECTION_NEEDED:
01618 {
01619
01620
01621
01622
01623
01624 while (conn->addr_cur != NULL)
01625 {
01626 struct addrinfo *addr_cur = conn->addr_cur;
01627
01628
01629 memcpy(&conn->raddr.addr, addr_cur->ai_addr,
01630 addr_cur->ai_addrlen);
01631 conn->raddr.salen = addr_cur->ai_addrlen;
01632
01633
01634 conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);
01635 if (conn->sock < 0)
01636 {
01637
01638
01639
01640
01641 if (addr_cur->ai_next != NULL)
01642 {
01643 conn->addr_cur = addr_cur->ai_next;
01644 continue;
01645 }
01646 appendPQExpBuffer(&conn->errorMessage,
01647 libpq_gettext("could not create socket: %s\n"),
01648 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01649 break;
01650 }
01651
01652
01653
01654
01655
01656
01657 if (!IS_AF_UNIX(addr_cur->ai_family))
01658 {
01659 if (!connectNoDelay(conn))
01660 {
01661 pqDropConnection(conn);
01662 conn->addr_cur = addr_cur->ai_next;
01663 continue;
01664 }
01665 }
01666 if (!pg_set_noblock(conn->sock))
01667 {
01668 appendPQExpBuffer(&conn->errorMessage,
01669 libpq_gettext("could not set socket to nonblocking mode: %s\n"),
01670 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01671 pqDropConnection(conn);
01672 conn->addr_cur = addr_cur->ai_next;
01673 continue;
01674 }
01675
01676 #ifdef F_SETFD
01677 if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
01678 {
01679 appendPQExpBuffer(&conn->errorMessage,
01680 libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
01681 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01682 pqDropConnection(conn);
01683 conn->addr_cur = addr_cur->ai_next;
01684 continue;
01685 }
01686 #endif
01687
01688 if (!IS_AF_UNIX(addr_cur->ai_family))
01689 {
01690 #ifndef WIN32
01691 int on = 1;
01692 #endif
01693 int usekeepalives = useKeepalives(conn);
01694 int err = 0;
01695
01696 if (usekeepalives < 0)
01697 {
01698 appendPQExpBuffer(&conn->errorMessage,
01699 libpq_gettext("keepalives parameter must be an integer\n"));
01700 err = 1;
01701 }
01702 else if (usekeepalives == 0)
01703 {
01704
01705 }
01706 #ifndef WIN32
01707 else if (setsockopt(conn->sock,
01708 SOL_SOCKET, SO_KEEPALIVE,
01709 (char *) &on, sizeof(on)) < 0)
01710 {
01711 appendPQExpBuffer(&conn->errorMessage,
01712 libpq_gettext("setsockopt(SO_KEEPALIVE) failed: %s\n"),
01713 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01714 err = 1;
01715 }
01716 else if (!setKeepalivesIdle(conn)
01717 || !setKeepalivesInterval(conn)
01718 || !setKeepalivesCount(conn))
01719 err = 1;
01720 #else
01721 #ifdef SIO_KEEPALIVE_VALS
01722 else if (!setKeepalivesWin32(conn))
01723 err = 1;
01724 #endif
01725 #endif
01726
01727 if (err)
01728 {
01729 pqDropConnection(conn);
01730 conn->addr_cur = addr_cur->ai_next;
01731 continue;
01732 }
01733 }
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758 conn->sigpipe_so = false;
01759 #ifdef MSG_NOSIGNAL
01760 conn->sigpipe_flag = true;
01761 #else
01762 conn->sigpipe_flag = false;
01763 #endif
01764
01765 #ifdef SO_NOSIGPIPE
01766 optval = 1;
01767 if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
01768 (char *) &optval, sizeof(optval)) == 0)
01769 {
01770 conn->sigpipe_so = true;
01771 conn->sigpipe_flag = false;
01772 }
01773 #endif
01774
01775
01776
01777
01778
01779 if (connect(conn->sock, addr_cur->ai_addr,
01780 addr_cur->ai_addrlen) < 0)
01781 {
01782 if (SOCK_ERRNO == EINPROGRESS ||
01783 SOCK_ERRNO == EWOULDBLOCK ||
01784 SOCK_ERRNO == EINTR ||
01785 SOCK_ERRNO == 0)
01786 {
01787
01788
01789
01790
01791
01792 conn->status = CONNECTION_STARTED;
01793 return PGRES_POLLING_WRITING;
01794 }
01795
01796 }
01797 else
01798 {
01799
01800
01801
01802
01803
01804 conn->status = CONNECTION_STARTED;
01805 goto keep_going;
01806 }
01807
01808
01809
01810
01811
01812
01813
01814 connectFailureMessage(conn, SOCK_ERRNO);
01815 pqDropConnection(conn);
01816
01817
01818
01819
01820 conn->addr_cur = addr_cur->ai_next;
01821 }
01822
01823
01824
01825
01826
01827 goto error_return;
01828 }
01829
01830 case CONNECTION_STARTED:
01831 {
01832 ACCEPT_TYPE_ARG3 optlen = sizeof(optval);
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844 if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
01845 (char *) &optval, &optlen) == -1)
01846 {
01847 appendPQExpBuffer(&conn->errorMessage,
01848 libpq_gettext("could not get socket error status: %s\n"),
01849 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01850 goto error_return;
01851 }
01852 else if (optval != 0)
01853 {
01854
01855
01856
01857
01858
01859 connectFailureMessage(conn, optval);
01860 pqDropConnection(conn);
01861
01862
01863
01864
01865
01866 if (conn->addr_cur->ai_next != NULL)
01867 {
01868 conn->addr_cur = conn->addr_cur->ai_next;
01869 conn->status = CONNECTION_NEEDED;
01870 goto keep_going;
01871 }
01872 goto error_return;
01873 }
01874
01875
01876 conn->laddr.salen = sizeof(conn->laddr.addr);
01877 if (getsockname(conn->sock,
01878 (struct sockaddr *) & conn->laddr.addr,
01879 &conn->laddr.salen) < 0)
01880 {
01881 appendPQExpBuffer(&conn->errorMessage,
01882 libpq_gettext("could not get client address from socket: %s\n"),
01883 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01884 goto error_return;
01885 }
01886
01887
01888
01889
01890 conn->status = CONNECTION_MADE;
01891 return PGRES_POLLING_WRITING;
01892 }
01893
01894 case CONNECTION_MADE:
01895 {
01896 char *startpacket;
01897 int packetlen;
01898
01899 #ifdef HAVE_UNIX_SOCKETS
01900
01901
01902
01903
01904
01905 if (conn->requirepeer && conn->requirepeer[0] &&
01906 IS_AF_UNIX(conn->raddr.addr.ss_family))
01907 {
01908 char pwdbuf[BUFSIZ];
01909 struct passwd pass_buf;
01910 struct passwd *pass;
01911 uid_t uid;
01912 gid_t gid;
01913
01914 errno = 0;
01915 if (getpeereid(conn->sock, &uid, &gid) != 0)
01916 {
01917
01918
01919
01920
01921 if (errno == ENOSYS)
01922 appendPQExpBuffer(&conn->errorMessage,
01923 libpq_gettext("requirepeer parameter is not supported on this platform\n"));
01924 else
01925 appendPQExpBuffer(&conn->errorMessage,
01926 libpq_gettext("could not get peer credentials: %s\n"),
01927 pqStrerror(errno, sebuf, sizeof(sebuf)));
01928 goto error_return;
01929 }
01930
01931 pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
01932
01933 if (pass == NULL)
01934 {
01935 appendPQExpBuffer(&conn->errorMessage,
01936 libpq_gettext("local user with ID %d does not exist\n"),
01937 (int) uid);
01938 goto error_return;
01939 }
01940
01941 if (strcmp(pass->pw_name, conn->requirepeer) != 0)
01942 {
01943 appendPQExpBuffer(&conn->errorMessage,
01944 libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
01945 conn->requirepeer, pass->pw_name);
01946 goto error_return;
01947 }
01948 }
01949 #endif
01950
01951 #ifdef USE_SSL
01952
01953
01954
01955
01956
01957 if (IS_AF_UNIX(conn->raddr.addr.ss_family))
01958 {
01959
01960 conn->allow_ssl_try = false;
01961 }
01962 if (conn->allow_ssl_try && !conn->wait_ssl_try &&
01963 conn->ssl == NULL)
01964 {
01965 ProtocolVersion pv;
01966
01967
01968
01969
01970
01971
01972
01973
01974 pv = htonl(NEGOTIATE_SSL_CODE);
01975 if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
01976 {
01977 appendPQExpBuffer(&conn->errorMessage,
01978 libpq_gettext("could not send SSL negotiation packet: %s\n"),
01979 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01980 goto error_return;
01981 }
01982
01983 conn->status = CONNECTION_SSL_STARTUP;
01984 return PGRES_POLLING_READING;
01985 }
01986 #endif
01987
01988
01989
01990
01991 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
01992 startpacket = pqBuildStartupPacket3(conn, &packetlen,
01993 EnvironmentOptions);
01994 else
01995 startpacket = pqBuildStartupPacket2(conn, &packetlen,
01996 EnvironmentOptions);
01997 if (!startpacket)
01998 {
01999
02000
02001
02002
02003 printfPQExpBuffer(&conn->errorMessage,
02004 libpq_gettext("out of memory\n"));
02005 goto error_return;
02006 }
02007
02008
02009
02010
02011
02012
02013
02014 if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
02015 {
02016 appendPQExpBuffer(&conn->errorMessage,
02017 libpq_gettext("could not send startup packet: %s\n"),
02018 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
02019 free(startpacket);
02020 goto error_return;
02021 }
02022
02023 free(startpacket);
02024
02025 conn->status = CONNECTION_AWAITING_RESPONSE;
02026 return PGRES_POLLING_READING;
02027 }
02028
02029
02030
02031
02032
02033 case CONNECTION_SSL_STARTUP:
02034 {
02035 #ifdef USE_SSL
02036 PostgresPollingStatusType pollres;
02037
02038
02039
02040
02041
02042 if (conn->ssl == NULL)
02043 {
02044
02045
02046
02047
02048
02049 char SSLok;
02050 int rdresult;
02051
02052 rdresult = pqReadData(conn);
02053 if (rdresult < 0)
02054 {
02055
02056 goto error_return;
02057 }
02058 if (rdresult == 0)
02059 {
02060
02061 return PGRES_POLLING_READING;
02062 }
02063 if (pqGetc(&SSLok, conn) < 0)
02064 {
02065
02066 return PGRES_POLLING_READING;
02067 }
02068 if (SSLok == 'S')
02069 {
02070
02071 conn->inStart = conn->inCursor;
02072
02073 if (pqsecure_initialize(conn) != 0)
02074 goto error_return;
02075 }
02076 else if (SSLok == 'N')
02077 {
02078
02079 conn->inStart = conn->inCursor;
02080
02081 if (conn->sslmode[0] == 'r' ||
02082 conn->sslmode[0] == 'v')
02083
02084 {
02085
02086 appendPQExpBuffer(&conn->errorMessage,
02087 libpq_gettext("server does not support SSL, but SSL was required\n"));
02088 goto error_return;
02089 }
02090
02091 conn->allow_ssl_try = false;
02092 conn->status = CONNECTION_MADE;
02093 return PGRES_POLLING_WRITING;
02094 }
02095 else if (SSLok == 'E')
02096 {
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107 conn->status = CONNECTION_AWAITING_RESPONSE;
02108 goto keep_going;
02109 }
02110 else
02111 {
02112 appendPQExpBuffer(&conn->errorMessage,
02113 libpq_gettext("received invalid response to SSL negotiation: %c\n"),
02114 SSLok);
02115 goto error_return;
02116 }
02117 }
02118
02119
02120
02121
02122 pollres = pqsecure_open_client(conn);
02123 if (pollres == PGRES_POLLING_OK)
02124 {
02125
02126 conn->status = CONNECTION_MADE;
02127 return PGRES_POLLING_WRITING;
02128 }
02129 if (pollres == PGRES_POLLING_FAILED)
02130 {
02131
02132
02133
02134
02135 if (conn->sslmode[0] == 'p'
02136 && conn->allow_ssl_try
02137 && !conn->wait_ssl_try)
02138 {
02139
02140 conn->allow_ssl_try = false;
02141
02142 pqDropConnection(conn);
02143 conn->status = CONNECTION_NEEDED;
02144 goto keep_going;
02145 }
02146 }
02147 return pollres;
02148 #else
02149
02150 goto error_return;
02151 #endif
02152 }
02153
02154
02155
02156
02157
02158 case CONNECTION_AWAITING_RESPONSE:
02159 {
02160 char beresp;
02161 int msgLength;
02162 int avail;
02163 AuthRequest areq;
02164
02165
02166
02167
02168
02169
02170 conn->inCursor = conn->inStart;
02171
02172
02173 if (pqGetc(&beresp, conn))
02174 {
02175
02176 return PGRES_POLLING_READING;
02177 }
02178
02179
02180
02181
02182
02183
02184 if (!(beresp == 'R' || beresp == 'E'))
02185 {
02186 appendPQExpBuffer(&conn->errorMessage,
02187 libpq_gettext(
02188 "expected authentication request from "
02189 "server, but received %c\n"),
02190 beresp);
02191 goto error_return;
02192 }
02193
02194 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02195 {
02196
02197 if (pqGetInt(&msgLength, 4, conn))
02198 {
02199
02200 return PGRES_POLLING_READING;
02201 }
02202 }
02203 else
02204 {
02205
02206 msgLength = 8;
02207 }
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217 if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
02218 {
02219 appendPQExpBuffer(&conn->errorMessage,
02220 libpq_gettext(
02221 "expected authentication request from "
02222 "server, but received %c\n"),
02223 beresp);
02224 goto error_return;
02225 }
02226
02227 if (beresp == 'E' && (msgLength < 8 || msgLength > 30000))
02228 {
02229
02230 conn->inCursor = conn->inStart + 1;
02231 if (pqGets_append(&conn->errorMessage, conn))
02232 {
02233
02234 return PGRES_POLLING_READING;
02235 }
02236
02237 conn->inStart = conn->inCursor;
02238
02239
02240
02241
02242
02243 appendPQExpBufferChar(&conn->errorMessage, '\n');
02244
02245
02246
02247
02248
02249 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02250 {
02251 conn->pversion = PG_PROTOCOL(2, 0);
02252
02253 pqDropConnection(conn);
02254 conn->status = CONNECTION_NEEDED;
02255 goto keep_going;
02256 }
02257
02258 goto error_return;
02259 }
02260
02261
02262
02263
02264
02265
02266
02267 msgLength -= 4;
02268 avail = conn->inEnd - conn->inCursor;
02269 if (avail < msgLength)
02270 {
02271
02272
02273
02274
02275
02276 if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
02277 conn))
02278 goto error_return;
02279
02280 return PGRES_POLLING_READING;
02281 }
02282
02283
02284 if (beresp == 'E')
02285 {
02286 if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
02287 {
02288 if (pqGetErrorNotice3(conn, true))
02289 {
02290
02291 return PGRES_POLLING_READING;
02292 }
02293 }
02294 else
02295 {
02296 if (pqGets_append(&conn->errorMessage, conn))
02297 {
02298
02299 return PGRES_POLLING_READING;
02300 }
02301 }
02302
02303 conn->inStart = conn->inCursor;
02304
02305 #ifdef USE_SSL
02306
02307
02308
02309
02310
02311 if (conn->sslmode[0] == 'a'
02312 && conn->ssl == NULL
02313 && conn->allow_ssl_try
02314 && conn->wait_ssl_try)
02315 {
02316
02317 conn->wait_ssl_try = false;
02318
02319 pqDropConnection(conn);
02320 conn->status = CONNECTION_NEEDED;
02321 goto keep_going;
02322 }
02323
02324
02325
02326
02327
02328 if (conn->sslmode[0] == 'p'
02329 && conn->allow_ssl_try
02330 && !conn->wait_ssl_try)
02331 {
02332
02333 conn->allow_ssl_try = false;
02334
02335 pqDropConnection(conn);
02336 conn->status = CONNECTION_NEEDED;
02337 goto keep_going;
02338 }
02339 #endif
02340
02341 goto error_return;
02342 }
02343
02344
02345 conn->auth_req_received = true;
02346
02347
02348 if (pqGetInt((int *) &areq, 4, conn))
02349 {
02350
02351 return PGRES_POLLING_READING;
02352 }
02353
02354
02355 if (areq == AUTH_REQ_MD5)
02356 {
02357 if (pqGetnchar(conn->md5Salt,
02358 sizeof(conn->md5Salt), conn))
02359 {
02360
02361 return PGRES_POLLING_READING;
02362 }
02363 }
02364 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
02365
02366
02367
02368
02369 if (areq == AUTH_REQ_GSS_CONT)
02370 {
02371 int llen = msgLength - 4;
02372
02373
02374
02375
02376
02377
02378 if (llen != conn->ginbuf.length)
02379 {
02380 if (conn->ginbuf.value)
02381 free(conn->ginbuf.value);
02382
02383 conn->ginbuf.length = llen;
02384 conn->ginbuf.value = malloc(llen);
02385 if (!conn->ginbuf.value)
02386 {
02387 printfPQExpBuffer(&conn->errorMessage,
02388 libpq_gettext("out of memory allocating GSSAPI buffer (%d)"),
02389 llen);
02390 goto error_return;
02391 }
02392 }
02393
02394 if (pqGetnchar(conn->ginbuf.value, llen, conn))
02395 {
02396
02397 return PGRES_POLLING_READING;
02398 }
02399 }
02400 #endif
02401
02402
02403
02404
02405 conn->inStart = conn->inCursor;
02406
02407
02408
02409
02410
02411
02412
02413
02414 if (pg_fe_sendauth(areq, conn) != STATUS_OK)
02415 {
02416 conn->errorMessage.len = strlen(conn->errorMessage.data);
02417 goto error_return;
02418 }
02419 conn->errorMessage.len = strlen(conn->errorMessage.data);
02420
02421
02422
02423
02424
02425
02426 if (pqFlush(conn))
02427 goto error_return;
02428
02429 if (areq == AUTH_REQ_OK)
02430 {
02431
02432 conn->status = CONNECTION_AUTH_OK;
02433
02434
02435
02436
02437
02438
02439 conn->asyncStatus = PGASYNC_BUSY;
02440 }
02441
02442
02443 goto keep_going;
02444 }
02445
02446 case CONNECTION_AUTH_OK:
02447 {
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460 if (PQisBusy(conn))
02461 return PGRES_POLLING_READING;
02462
02463 res = PQgetResult(conn);
02464
02465
02466
02467
02468
02469 if (res)
02470 {
02471 if (res->resultStatus != PGRES_FATAL_ERROR)
02472 appendPQExpBuffer(&conn->errorMessage,
02473 libpq_gettext("unexpected message from server during startup\n"));
02474 else if (conn->send_appname &&
02475 (conn->appname || conn->fbappname))
02476 {
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487 const char *sqlstate;
02488
02489 sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
02490 if (sqlstate &&
02491 strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
02492 {
02493 PQclear(res);
02494 conn->send_appname = false;
02495
02496 pqDropConnection(conn);
02497 conn->status = CONNECTION_NEEDED;
02498 goto keep_going;
02499 }
02500 }
02501
02502
02503
02504
02505
02506
02507
02508 if (conn->errorMessage.len <= 0 ||
02509 conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
02510 appendPQExpBufferChar(&conn->errorMessage, '\n');
02511 PQclear(res);
02512 goto error_return;
02513 }
02514
02515
02516 pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);
02517 conn->addrlist = NULL;
02518 conn->addr_cur = NULL;
02519
02520
02521 if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
02522 {
02523 conn->status = CONNECTION_SETENV;
02524 conn->setenv_state = SETENV_STATE_CLIENT_ENCODING_SEND;
02525 conn->next_eo = EnvironmentOptions;
02526 return PGRES_POLLING_WRITING;
02527 }
02528
02529
02530 conn->status = CONNECTION_OK;
02531 return PGRES_POLLING_OK;
02532 }
02533
02534 case CONNECTION_SETENV:
02535
02536
02537
02538
02539
02540
02541
02542 conn->status = CONNECTION_OK;
02543
02544 switch (pqSetenvPoll(conn))
02545 {
02546 case PGRES_POLLING_OK:
02547 break;
02548
02549 case PGRES_POLLING_READING:
02550 conn->status = CONNECTION_SETENV;
02551 return PGRES_POLLING_READING;
02552
02553 case PGRES_POLLING_WRITING:
02554 conn->status = CONNECTION_SETENV;
02555 return PGRES_POLLING_WRITING;
02556
02557 default:
02558 goto error_return;
02559 }
02560
02561
02562 conn->status = CONNECTION_OK;
02563 return PGRES_POLLING_OK;
02564
02565 default:
02566 appendPQExpBuffer(&conn->errorMessage,
02567 libpq_gettext("invalid connection state %d, "
02568 "probably indicative of memory corruption\n"),
02569 conn->status);
02570 goto error_return;
02571 }
02572
02573
02574
02575 error_return:
02576
02577 dot_pg_pass_warning(conn);
02578
02579
02580
02581
02582
02583
02584
02585
02586 conn->status = CONNECTION_BAD;
02587 return PGRES_POLLING_FAILED;
02588 }
02589
02590
02591
02592
02593
02594
02595
02596
02597 static PGPing
02598 internal_ping(PGconn *conn)
02599 {
02600
02601 if (!conn || !conn->options_valid)
02602 return PQPING_NO_ATTEMPT;
02603
02604
02605 if (conn->status != CONNECTION_BAD)
02606 (void) connectDBComplete(conn);
02607
02608
02609 if (conn->status != CONNECTION_BAD)
02610 return PQPING_OK;
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621 if (conn->auth_req_received)
02622 return PQPING_OK;
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638 if (strlen(conn->last_sqlstate) != 5)
02639 return PQPING_NO_RESPONSE;
02640
02641
02642
02643
02644
02645 if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
02646 return PQPING_REJECT;
02647
02648
02649
02650
02651
02652
02653
02654 return PQPING_OK;
02655 }
02656
02657
02658
02659
02660
02661
02662 static PGconn *
02663 makeEmptyPGconn(void)
02664 {
02665 PGconn *conn;
02666
02667 #ifdef WIN32
02668
02669
02670
02671
02672 WSADATA wsaData;
02673
02674 if (WSAStartup(MAKEWORD(1, 1), &wsaData))
02675 return NULL;
02676 WSASetLastError(0);
02677 #endif
02678
02679 conn = (PGconn *) malloc(sizeof(PGconn));
02680 if (conn == NULL)
02681 {
02682 #ifdef WIN32
02683 WSACleanup();
02684 #endif
02685 return conn;
02686 }
02687
02688
02689 MemSet(conn, 0, sizeof(PGconn));
02690
02691
02692 conn->noticeHooks.noticeRec = defaultNoticeReceiver;
02693 conn->noticeHooks.noticeProc = defaultNoticeProcessor;
02694
02695 conn->status = CONNECTION_BAD;
02696 conn->asyncStatus = PGASYNC_IDLE;
02697 conn->xactStatus = PQTRANS_IDLE;
02698 conn->options_valid = false;
02699 conn->nonblocking = false;
02700 conn->setenv_state = SETENV_STATE_IDLE;
02701 conn->client_encoding = PG_SQL_ASCII;
02702 conn->std_strings = false;
02703 conn->verbosity = PQERRORS_DEFAULT;
02704 conn->sock = -1;
02705 conn->auth_req_received = false;
02706 conn->password_needed = false;
02707 conn->dot_pgpass_used = false;
02708 #ifdef USE_SSL
02709 conn->allow_ssl_try = true;
02710 conn->wait_ssl_try = false;
02711 #endif
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724 conn->inBufSize = 16 * 1024;
02725 conn->inBuffer = (char *) malloc(conn->inBufSize);
02726 conn->outBufSize = 16 * 1024;
02727 conn->outBuffer = (char *) malloc(conn->outBufSize);
02728 conn->rowBufLen = 32;
02729 conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
02730 initPQExpBuffer(&conn->errorMessage);
02731 initPQExpBuffer(&conn->workBuffer);
02732
02733 if (conn->inBuffer == NULL ||
02734 conn->outBuffer == NULL ||
02735 conn->rowBuf == NULL ||
02736 PQExpBufferBroken(&conn->errorMessage) ||
02737 PQExpBufferBroken(&conn->workBuffer))
02738 {
02739
02740 freePGconn(conn);
02741 conn = NULL;
02742 }
02743
02744 return conn;
02745 }
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756 static void
02757 freePGconn(PGconn *conn)
02758 {
02759 int i;
02760
02761
02762 for (i = 0; i < conn->nEvents; i++)
02763 {
02764 PGEventConnDestroy evt;
02765
02766 evt.conn = conn;
02767 (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
02768 conn->events[i].passThrough);
02769 free(conn->events[i].name);
02770 }
02771
02772 if (conn->client_encoding_initial)
02773 free(conn->client_encoding_initial);
02774 if (conn->events)
02775 free(conn->events);
02776 if (conn->pghost)
02777 free(conn->pghost);
02778 if (conn->pghostaddr)
02779 free(conn->pghostaddr);
02780 if (conn->pgport)
02781 free(conn->pgport);
02782 if (conn->pgunixsocket)
02783 free(conn->pgunixsocket);
02784 if (conn->pgtty)
02785 free(conn->pgtty);
02786 if (conn->connect_timeout)
02787 free(conn->connect_timeout);
02788 if (conn->pgoptions)
02789 free(conn->pgoptions);
02790 if (conn->appname)
02791 free(conn->appname);
02792 if (conn->fbappname)
02793 free(conn->fbappname);
02794 if (conn->dbName)
02795 free(conn->dbName);
02796 if (conn->replication)
02797 free(conn->replication);
02798 if (conn->pguser)
02799 free(conn->pguser);
02800 if (conn->pgpass)
02801 free(conn->pgpass);
02802 if (conn->keepalives)
02803 free(conn->keepalives);
02804 if (conn->keepalives_idle)
02805 free(conn->keepalives_idle);
02806 if (conn->keepalives_interval)
02807 free(conn->keepalives_interval);
02808 if (conn->keepalives_count)
02809 free(conn->keepalives_count);
02810 if (conn->sslmode)
02811 free(conn->sslmode);
02812 if (conn->sslcert)
02813 free(conn->sslcert);
02814 if (conn->sslkey)
02815 free(conn->sslkey);
02816 if (conn->sslrootcert)
02817 free(conn->sslrootcert);
02818 if (conn->sslcrl)
02819 free(conn->sslcrl);
02820 if (conn->sslcompression)
02821 free(conn->sslcompression);
02822 if (conn->requirepeer)
02823 free(conn->requirepeer);
02824 #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
02825 if (conn->krbsrvname)
02826 free(conn->krbsrvname);
02827 #endif
02828 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
02829 if (conn->gsslib)
02830 free(conn->gsslib);
02831 #endif
02832
02833 if (conn->last_query)
02834 free(conn->last_query);
02835 if (conn->inBuffer)
02836 free(conn->inBuffer);
02837 if (conn->outBuffer)
02838 free(conn->outBuffer);
02839 if (conn->rowBuf)
02840 free(conn->rowBuf);
02841 termPQExpBuffer(&conn->errorMessage);
02842 termPQExpBuffer(&conn->workBuffer);
02843
02844 free(conn);
02845
02846 #ifdef WIN32
02847 WSACleanup();
02848 #endif
02849 }
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859 static void
02860 closePGconn(PGconn *conn)
02861 {
02862 PGnotify *notify;
02863 pgParameterStatus *pstatus;
02864
02865
02866
02867
02868
02869 if (conn->sock >= 0 && conn->status == CONNECTION_OK)
02870 {
02871
02872
02873
02874
02875 pqPutMsgStart('X', false, conn);
02876 pqPutMsgEnd(conn);
02877 pqFlush(conn);
02878 }
02879
02880
02881
02882
02883
02884
02885
02886 conn->nonblocking = FALSE;
02887
02888
02889
02890
02891 pqDropConnection(conn);
02892 conn->status = CONNECTION_BAD;
02893
02894 conn->asyncStatus = PGASYNC_IDLE;
02895 pqClearAsyncResult(conn);
02896 pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);
02897 conn->addrlist = NULL;
02898 conn->addr_cur = NULL;
02899 notify = conn->notifyHead;
02900 while (notify != NULL)
02901 {
02902 PGnotify *prev = notify;
02903
02904 notify = notify->next;
02905 free(prev);
02906 }
02907 conn->notifyHead = conn->notifyTail = NULL;
02908 pstatus = conn->pstatus;
02909 while (pstatus != NULL)
02910 {
02911 pgParameterStatus *prev = pstatus;
02912
02913 pstatus = pstatus->next;
02914 free(prev);
02915 }
02916 conn->pstatus = NULL;
02917 if (conn->lobjfuncs)
02918 free(conn->lobjfuncs);
02919 conn->lobjfuncs = NULL;
02920 #ifdef ENABLE_GSS
02921 {
02922 OM_uint32 min_s;
02923
02924 if (conn->gctx)
02925 gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
02926 if (conn->gtarg_nam)
02927 gss_release_name(&min_s, &conn->gtarg_nam);
02928 if (conn->ginbuf.length)
02929 gss_release_buffer(&min_s, &conn->ginbuf);
02930 if (conn->goutbuf.length)
02931 gss_release_buffer(&min_s, &conn->goutbuf);
02932 }
02933 #endif
02934 #ifdef ENABLE_SSPI
02935 if (conn->ginbuf.length)
02936 free(conn->ginbuf.value);
02937 conn->ginbuf.length = 0;
02938 conn->ginbuf.value = NULL;
02939 if (conn->sspitarget)
02940 free(conn->sspitarget);
02941 conn->sspitarget = NULL;
02942 if (conn->sspicred)
02943 {
02944 FreeCredentialsHandle(conn->sspicred);
02945 free(conn->sspicred);
02946 conn->sspicred = NULL;
02947 }
02948 if (conn->sspictx)
02949 {
02950 DeleteSecurityContext(conn->sspictx);
02951 free(conn->sspictx);
02952 conn->sspictx = NULL;
02953 }
02954 #endif
02955 }
02956
02957
02958
02959
02960
02961 void
02962 PQfinish(PGconn *conn)
02963 {
02964 if (conn)
02965 {
02966 closePGconn(conn);
02967 freePGconn(conn);
02968 }
02969 }
02970
02971
02972
02973
02974
02975 void
02976 PQreset(PGconn *conn)
02977 {
02978 if (conn)
02979 {
02980 closePGconn(conn);
02981
02982 if (connectDBStart(conn) && connectDBComplete(conn))
02983 {
02984
02985
02986
02987
02988 int i;
02989
02990 for (i = 0; i < conn->nEvents; i++)
02991 {
02992 PGEventConnReset evt;
02993
02994 evt.conn = conn;
02995 if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
02996 conn->events[i].passThrough))
02997 {
02998 conn->status = CONNECTION_BAD;
02999 printfPQExpBuffer(&conn->errorMessage,
03000 libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
03001 conn->events[i].name);
03002 break;
03003 }
03004 }
03005 }
03006 }
03007 }
03008
03009
03010
03011
03012
03013
03014
03015
03016 int
03017 PQresetStart(PGconn *conn)
03018 {
03019 if (conn)
03020 {
03021 closePGconn(conn);
03022
03023 return connectDBStart(conn);
03024 }
03025
03026 return 0;
03027 }
03028
03029
03030
03031
03032
03033
03034
03035 PostgresPollingStatusType
03036 PQresetPoll(PGconn *conn)
03037 {
03038 if (conn)
03039 {
03040 PostgresPollingStatusType status = PQconnectPoll(conn);
03041
03042 if (status == PGRES_POLLING_OK)
03043 {
03044
03045
03046
03047
03048 int i;
03049
03050 for (i = 0; i < conn->nEvents; i++)
03051 {
03052 PGEventConnReset evt;
03053
03054 evt.conn = conn;
03055 if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
03056 conn->events[i].passThrough))
03057 {
03058 conn->status = CONNECTION_BAD;
03059 printfPQExpBuffer(&conn->errorMessage,
03060 libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
03061 conn->events[i].name);
03062 return PGRES_POLLING_FAILED;
03063 }
03064 }
03065 }
03066
03067 return status;
03068 }
03069
03070 return PGRES_POLLING_FAILED;
03071 }
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082 PGcancel *
03083 PQgetCancel(PGconn *conn)
03084 {
03085 PGcancel *cancel;
03086
03087 if (!conn)
03088 return NULL;
03089
03090 if (conn->sock < 0)
03091 return NULL;
03092
03093 cancel = malloc(sizeof(PGcancel));
03094 if (cancel == NULL)
03095 return NULL;
03096
03097 memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr));
03098 cancel->be_pid = conn->be_pid;
03099 cancel->be_key = conn->be_key;
03100
03101 return cancel;
03102 }
03103
03104
03105 void
03106 PQfreeCancel(PGcancel *cancel)
03107 {
03108 if (cancel)
03109 free(cancel);
03110 }
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133 static int
03134 internal_cancel(SockAddr *raddr, int be_pid, int be_key,
03135 char *errbuf, int errbufsize)
03136 {
03137 int save_errno = SOCK_ERRNO;
03138 int tmpsock = -1;
03139 char sebuf[256];
03140 int maxlen;
03141 struct
03142 {
03143 uint32 packetlen;
03144 CancelRequestPacket cp;
03145 } crp;
03146
03147
03148
03149
03150
03151 if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) < 0)
03152 {
03153 strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
03154 goto cancel_errReturn;
03155 }
03156 retry3:
03157 if (connect(tmpsock, (struct sockaddr *) & raddr->addr,
03158 raddr->salen) < 0)
03159 {
03160 if (SOCK_ERRNO == EINTR)
03161
03162 goto retry3;
03163 strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
03164 goto cancel_errReturn;
03165 }
03166
03167
03168
03169
03170
03171
03172
03173 crp.packetlen = htonl((uint32) sizeof(crp));
03174 crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE);
03175 crp.cp.backendPID = htonl(be_pid);
03176 crp.cp.cancelAuthCode = htonl(be_key);
03177
03178 retry4:
03179 if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
03180 {
03181 if (SOCK_ERRNO == EINTR)
03182
03183 goto retry4;
03184 strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
03185 goto cancel_errReturn;
03186 }
03187
03188
03189
03190
03191
03192
03193
03194
03195 retry5:
03196 if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
03197 {
03198 if (SOCK_ERRNO == EINTR)
03199
03200 goto retry5;
03201
03202 }
03203
03204
03205 closesocket(tmpsock);
03206 SOCK_ERRNO_SET(save_errno);
03207 return TRUE;
03208
03209 cancel_errReturn:
03210
03211
03212
03213
03214
03215 maxlen = errbufsize - strlen(errbuf) - 2;
03216 if (maxlen >= 0)
03217 {
03218 strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
03219 maxlen);
03220 strcat(errbuf, "\n");
03221 }
03222 if (tmpsock >= 0)
03223 closesocket(tmpsock);
03224 SOCK_ERRNO_SET(save_errno);
03225 return FALSE;
03226 }
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237 int
03238 PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
03239 {
03240 if (!cancel)
03241 {
03242 strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
03243 return FALSE;
03244 }
03245
03246 return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
03247 errbuf, errbufsize);
03248 }
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262 int
03263 PQrequestCancel(PGconn *conn)
03264 {
03265 int r;
03266
03267
03268 if (!conn)
03269 return FALSE;
03270
03271 if (conn->sock < 0)
03272 {
03273 strlcpy(conn->errorMessage.data,
03274 "PQrequestCancel() -- connection is not open\n",
03275 conn->errorMessage.maxlen);
03276 conn->errorMessage.len = strlen(conn->errorMessage.data);
03277
03278 return FALSE;
03279 }
03280
03281 r = internal_cancel(&conn->raddr, conn->be_pid, conn->be_key,
03282 conn->errorMessage.data, conn->errorMessage.maxlen);
03283
03284 if (!r)
03285 conn->errorMessage.len = strlen(conn->errorMessage.data);
03286
03287 return r;
03288 }
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306 int
03307 pqPacketSend(PGconn *conn, char pack_type,
03308 const void *buf, size_t buf_len)
03309 {
03310
03311 if (pqPutMsgStart(pack_type, true, conn))
03312 return STATUS_ERROR;
03313
03314
03315 if (pqPutnchar(buf, buf_len, conn))
03316 return STATUS_ERROR;
03317
03318
03319 if (pqPutMsgEnd(conn))
03320 return STATUS_ERROR;
03321
03322
03323 if (pqFlush(conn))
03324 return STATUS_ERROR;
03325
03326 return STATUS_OK;
03327 }
03328
03329 #ifdef USE_LDAP
03330
03331 #define LDAP_URL "ldap://"
03332 #define LDAP_DEF_PORT 389
03333 #define PGLDAP_TIMEOUT 2
03334
03335 #define ld_is_sp_tab(x) ((x) == ' ' || (x) == '\t')
03336 #define ld_is_nl_cr(x) ((x) == '\r' || (x) == '\n')
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358 static int
03359 ldapServiceLookup(const char *purl, PQconninfoOption *options,
03360 PQExpBuffer errorMessage)
03361 {
03362 int port = LDAP_DEF_PORT,
03363 scope,
03364 rc,
03365 msgid,
03366 size,
03367 state,
03368 oldstate,
03369 i;
03370 bool found_keyword;
03371 char *url,
03372 *hostname,
03373 *portstr,
03374 *endptr,
03375 *dn,
03376 *scopestr,
03377 *filter,
03378 *result,
03379 *p,
03380 *p1 = NULL,
03381 *optname = NULL,
03382 *optval = NULL;
03383 char *attrs[2] = {NULL, NULL};
03384 LDAP *ld = NULL;
03385 LDAPMessage *res,
03386 *entry;
03387 struct berval **values;
03388 LDAP_TIMEVAL time = {PGLDAP_TIMEOUT, 0};
03389
03390 if ((url = strdup(purl)) == NULL)
03391 {
03392 printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
03393 return 3;
03394 }
03395
03396
03397
03398
03399
03400
03401
03402 if (pg_strncasecmp(url, LDAP_URL, strlen(LDAP_URL)) != 0)
03403 {
03404 printfPQExpBuffer(errorMessage,
03405 libpq_gettext("invalid LDAP URL \"%s\": scheme must be ldap://\n"), purl);
03406 free(url);
03407 return 3;
03408 }
03409
03410
03411 hostname = url + strlen(LDAP_URL);
03412 if (*hostname == '/')
03413 hostname = DefaultHost;
03414
03415
03416 p = strchr(url + strlen(LDAP_URL), '/');
03417 if (p == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
03418 {
03419 printfPQExpBuffer(errorMessage, libpq_gettext(
03420 "invalid LDAP URL \"%s\": missing distinguished name\n"), purl);
03421 free(url);
03422 return 3;
03423 }
03424 *p = '\0';
03425 dn = p + 1;
03426
03427
03428 if ((p = strchr(dn, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
03429 {
03430 printfPQExpBuffer(errorMessage, libpq_gettext(
03431 "invalid LDAP URL \"%s\": must have exactly one attribute\n"), purl);
03432 free(url);
03433 return 3;
03434 }
03435 *p = '\0';
03436 attrs[0] = p + 1;
03437
03438
03439 if ((p = strchr(attrs[0], '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
03440 {
03441 printfPQExpBuffer(errorMessage, libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"), purl);
03442 free(url);
03443 return 3;
03444 }
03445 *p = '\0';
03446 scopestr = p + 1;
03447
03448
03449 if ((p = strchr(scopestr, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
03450 {
03451 printfPQExpBuffer(errorMessage,
03452 libpq_gettext("invalid LDAP URL \"%s\": no filter\n"), purl);
03453 free(url);
03454 return 3;
03455 }
03456 *p = '\0';
03457 filter = p + 1;
03458 if ((p = strchr(filter, '?')) != NULL)
03459 *p = '\0';
03460
03461
03462 if ((p1 = strchr(hostname, ':')) != NULL)
03463 {
03464 long lport;
03465
03466 *p1 = '\0';
03467 portstr = p1 + 1;
03468 errno = 0;
03469 lport = strtol(portstr, &endptr, 10);
03470 if (*portstr == '\0' || *endptr != '\0' || errno || lport < 0 || lport > 65535)
03471 {
03472 printfPQExpBuffer(errorMessage, libpq_gettext(
03473 "invalid LDAP URL \"%s\": invalid port number\n"), purl);
03474 free(url);
03475 return 3;
03476 }
03477 port = (int) lport;
03478 }
03479
03480
03481 if (strchr(attrs[0], ',') != NULL)
03482 {
03483 printfPQExpBuffer(errorMessage, libpq_gettext(
03484 "invalid LDAP URL \"%s\": must have exactly one attribute\n"), purl);
03485 free(url);
03486 return 3;
03487 }
03488
03489
03490 if (pg_strcasecmp(scopestr, "base") == 0)
03491 scope = LDAP_SCOPE_BASE;
03492 else if (pg_strcasecmp(scopestr, "one") == 0)
03493 scope = LDAP_SCOPE_ONELEVEL;
03494 else if (pg_strcasecmp(scopestr, "sub") == 0)
03495 scope = LDAP_SCOPE_SUBTREE;
03496 else
03497 {
03498 printfPQExpBuffer(errorMessage, libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"), purl);
03499 free(url);
03500 return 3;
03501 }
03502
03503
03504 if ((ld = ldap_init(hostname, port)) == NULL)
03505 {
03506 printfPQExpBuffer(errorMessage,
03507 libpq_gettext("could not create LDAP structure\n"));
03508 free(url);
03509 return 3;
03510 }
03511
03512
03513
03514
03515
03516 if ((msgid = ldap_simple_bind(ld, NULL, NULL)) == -1)
03517 {
03518
03519 free(url);
03520 ldap_unbind(ld);
03521 return 2;
03522 }
03523
03524
03525 res = NULL;
03526 if ((rc = ldap_result(ld, msgid, LDAP_MSG_ALL, &time, &res)) == -1 ||
03527 res == NULL)
03528 {
03529 if (res != NULL)
03530 {
03531
03532 ldap_msgfree(res);
03533 }
03534
03535 free(url);
03536 ldap_unbind(ld);
03537 return 2;
03538 }
03539 ldap_msgfree(res);
03540
03541
03542 res = NULL;
03543 if ((rc = ldap_search_st(ld, dn, scope, filter, attrs, 0, &time, &res))
03544 != LDAP_SUCCESS)
03545 {
03546 if (res != NULL)
03547 ldap_msgfree(res);
03548 printfPQExpBuffer(errorMessage,
03549 libpq_gettext("lookup on LDAP server failed: %s\n"),
03550 ldap_err2string(rc));
03551 ldap_unbind(ld);
03552 free(url);
03553 return 1;
03554 }
03555
03556
03557 if ((rc = ldap_count_entries(ld, res)) != 1)
03558 {
03559 printfPQExpBuffer(errorMessage,
03560 rc ? libpq_gettext("more than one entry found on LDAP lookup\n")
03561 : libpq_gettext("no entry found on LDAP lookup\n"));
03562 ldap_msgfree(res);
03563 ldap_unbind(ld);
03564 free(url);
03565 return 1;
03566 }
03567
03568
03569 if ((entry = ldap_first_entry(ld, res)) == NULL)
03570 {
03571
03572 printfPQExpBuffer(errorMessage,
03573 libpq_gettext("no entry found on LDAP lookup\n"));
03574 ldap_msgfree(res);
03575 ldap_unbind(ld);
03576 free(url);
03577 return 1;
03578 }
03579
03580
03581 if ((values = ldap_get_values_len(ld, entry, attrs[0])) == NULL)
03582 {
03583 printfPQExpBuffer(errorMessage,
03584 libpq_gettext("attribute has no values on LDAP lookup\n"));
03585 ldap_msgfree(res);
03586 ldap_unbind(ld);
03587 free(url);
03588 return 1;
03589 }
03590
03591 ldap_msgfree(res);
03592 free(url);
03593
03594 if (values[0] == NULL)
03595 {
03596 printfPQExpBuffer(errorMessage,
03597 libpq_gettext("attribute has no values on LDAP lookup\n"));
03598 ldap_value_free_len(values);
03599 ldap_unbind(ld);
03600 return 1;
03601 }
03602
03603
03604 size = 1;
03605 for (i = 0; values[i] != NULL; i++)
03606 size += values[i]->bv_len + 1;
03607 if ((result = malloc(size)) == NULL)
03608 {
03609 printfPQExpBuffer(errorMessage,
03610 libpq_gettext("out of memory\n"));
03611 ldap_value_free_len(values);
03612 ldap_unbind(ld);
03613 return 3;
03614 }
03615 p = result;
03616 for (i = 0; values[i] != NULL; i++)
03617 {
03618 memcpy(p, values[i]->bv_val, values[i]->bv_len);
03619 p += values[i]->bv_len;
03620 *(p++) = '\n';
03621 }
03622 *p = '\0';
03623
03624 ldap_value_free_len(values);
03625 ldap_unbind(ld);
03626
03627
03628 oldstate = state = 0;
03629 for (p = result; *p != '\0'; ++p)
03630 {
03631 switch (state)
03632 {
03633 case 0:
03634 if (!ld_is_sp_tab(*p) && !ld_is_nl_cr(*p))
03635 {
03636 optname = p;
03637 state = 1;
03638 }
03639 break;
03640 case 1:
03641 if (ld_is_sp_tab(*p))
03642 {
03643 *p = '\0';
03644 state = 2;
03645 }
03646 else if (ld_is_nl_cr(*p))
03647 {
03648 printfPQExpBuffer(errorMessage, libpq_gettext(
03649 "missing \"=\" after \"%s\" in connection info string\n"),
03650 optname);
03651 free(result);
03652 return 3;
03653 }
03654 else if (*p == '=')
03655 {
03656 *p = '\0';
03657 state = 3;
03658 }
03659 break;
03660 case 2:
03661 if (*p == '=')
03662 {
03663 state = 3;
03664 }
03665 else if (!ld_is_sp_tab(*p))
03666 {
03667 printfPQExpBuffer(errorMessage, libpq_gettext(
03668 "missing \"=\" after \"%s\" in connection info string\n"),
03669 optname);
03670 free(result);
03671 return 3;
03672 }
03673 break;
03674 case 3:
03675 if (*p == '\'')
03676 {
03677 optval = p + 1;
03678 p1 = p + 1;
03679 state = 5;
03680 }
03681 else if (ld_is_nl_cr(*p))
03682 {
03683 optval = optname + strlen(optname);
03684 state = 0;
03685 }
03686 else if (!ld_is_sp_tab(*p))
03687 {
03688 optval = p;
03689 state = 4;
03690 }
03691 break;
03692 case 4:
03693 if (ld_is_sp_tab(*p) || ld_is_nl_cr(*p))
03694 {
03695 *p = '\0';
03696 state = 0;
03697 }
03698 break;
03699 case 5:
03700 if (*p == '\'')
03701 {
03702 *p1 = '\0';
03703 state = 0;
03704 }
03705 else if (*p == '\\')
03706 state = 6;
03707 else
03708 *(p1++) = *p;
03709 break;
03710 case 6:
03711 *(p1++) = *p;
03712 state = 5;
03713 break;
03714 }
03715
03716 if (state == 0 && oldstate != 0)
03717 {
03718 found_keyword = false;
03719 for (i = 0; options[i].keyword; i++)
03720 {
03721 if (strcmp(options[i].keyword, optname) == 0)
03722 {
03723 if (options[i].val == NULL)
03724 options[i].val = strdup(optval);
03725 found_keyword = true;
03726 break;
03727 }
03728 }
03729 if (!found_keyword)
03730 {
03731 printfPQExpBuffer(errorMessage,
03732 libpq_gettext("invalid connection option \"%s\"\n"),
03733 optname);
03734 free(result);
03735 return 1;
03736 }
03737 optname = NULL;
03738 optval = NULL;
03739 }
03740 oldstate = state;
03741 }
03742
03743 free(result);
03744
03745 if (state == 5 || state == 6)
03746 {
03747 printfPQExpBuffer(errorMessage, libpq_gettext(
03748 "unterminated quoted string in connection info string\n"));
03749 return 3;
03750 }
03751
03752 return 0;
03753 }
03754 #endif
03755
03756 #define MAXBUFSIZE 256
03757
03758 static int
03759 parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
03760 {
03761 const char *service = conninfo_getval(options, "service");
03762 char serviceFile[MAXPGPATH];
03763 char *env;
03764 bool group_found = false;
03765 int status;
03766 struct stat stat_buf;
03767
03768
03769
03770
03771
03772
03773 if (service == NULL)
03774 service = getenv("PGSERVICE");
03775
03776 if (service == NULL)
03777 return 0;
03778
03779 if ((env = getenv("PGSERVICEFILE")) != NULL)
03780 strlcpy(serviceFile, env, sizeof(serviceFile));
03781 else
03782 {
03783 char homedir[MAXPGPATH];
03784
03785 if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
03786 {
03787 printfPQExpBuffer(errorMessage, libpq_gettext("could not get home directory to locate service definition file"));
03788 return 1;
03789 }
03790 snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
03791 errno = 0;
03792 if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT)
03793 goto next_file;
03794 }
03795
03796 status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
03797 if (group_found || status != 0)
03798 return status;
03799
03800 next_file:
03801
03802
03803
03804
03805
03806 snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
03807 getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
03808 errno = 0;
03809 if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT)
03810 goto last_file;
03811
03812 status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
03813 if (status != 0)
03814 return status;
03815
03816 last_file:
03817 if (!group_found)
03818 {
03819 printfPQExpBuffer(errorMessage,
03820 libpq_gettext("definition of service \"%s\" not found\n"), service);
03821 return 3;
03822 }
03823
03824 return 0;
03825 }
03826
03827 static int
03828 parseServiceFile(const char *serviceFile,
03829 const char *service,
03830 PQconninfoOption *options,
03831 PQExpBuffer errorMessage,
03832 bool *group_found)
03833 {
03834 int linenr = 0,
03835 i;
03836 FILE *f;
03837 char buf[MAXBUFSIZE],
03838 *line;
03839
03840 f = fopen(serviceFile, "r");
03841 if (f == NULL)
03842 {
03843 printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
03844 serviceFile);
03845 return 1;
03846 }
03847
03848 while ((line = fgets(buf, sizeof(buf), f)) != NULL)
03849 {
03850 linenr++;
03851
03852 if (strlen(line) >= sizeof(buf) - 1)
03853 {
03854 fclose(f);
03855 printfPQExpBuffer(errorMessage,
03856 libpq_gettext("line %d too long in service file \"%s\"\n"),
03857 linenr,
03858 serviceFile);
03859 return 2;
03860 }
03861
03862
03863 if (strlen(line) && line[strlen(line) - 1] == '\n')
03864 line[strlen(line) - 1] = 0;
03865
03866
03867 while (*line && isspace((unsigned char) line[0]))
03868 line++;
03869
03870
03871 if (strlen(line) == 0 || line[0] == '#')
03872 continue;
03873
03874
03875 if (line[0] == '[')
03876 {
03877 if (*group_found)
03878 {
03879
03880 fclose(f);
03881 return 0;
03882 }
03883
03884 if (strncmp(line + 1, service, strlen(service)) == 0 &&
03885 line[strlen(service) + 1] == ']')
03886 *group_found = true;
03887 else
03888 *group_found = false;
03889 }
03890 else
03891 {
03892 if (*group_found)
03893 {
03894
03895
03896
03897 char *key,
03898 *val;
03899 bool found_keyword;
03900
03901 #ifdef USE_LDAP
03902 if (strncmp(line, "ldap", 4) == 0)
03903 {
03904 int rc = ldapServiceLookup(line, options, errorMessage);
03905
03906
03907 switch (rc)
03908 {
03909 case 0:
03910 fclose(f);
03911 return 0;
03912 case 1:
03913 case 3:
03914 fclose(f);
03915 return 3;
03916 case 2:
03917 continue;
03918 }
03919 }
03920 #endif
03921
03922 key = line;
03923 val = strchr(line, '=');
03924 if (val == NULL)
03925 {
03926 printfPQExpBuffer(errorMessage,
03927 libpq_gettext("syntax error in service file \"%s\", line %d\n"),
03928 serviceFile,
03929 linenr);
03930 fclose(f);
03931 return 3;
03932 }
03933 *val++ = '\0';
03934
03935
03936
03937
03938
03939 found_keyword = false;
03940 for (i = 0; options[i].keyword; i++)
03941 {
03942 if (strcmp(options[i].keyword, key) == 0)
03943 {
03944 if (options[i].val == NULL)
03945 options[i].val = strdup(val);
03946 found_keyword = true;
03947 break;
03948 }
03949 }
03950
03951 if (!found_keyword)
03952 {
03953 printfPQExpBuffer(errorMessage,
03954 libpq_gettext("syntax error in service file \"%s\", line %d\n"),
03955 serviceFile,
03956 linenr);
03957 fclose(f);
03958 return 3;
03959 }
03960 }
03961 }
03962 }
03963
03964 fclose(f);
03965
03966 return 0;
03967 }
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984
03985 PQconninfoOption *
03986 PQconninfoParse(const char *conninfo, char **errmsg)
03987 {
03988 PQExpBufferData errorBuf;
03989 PQconninfoOption *connOptions;
03990
03991 if (errmsg)
03992 *errmsg = NULL;
03993 initPQExpBuffer(&errorBuf);
03994 if (PQExpBufferDataBroken(errorBuf))
03995 return NULL;
03996 connOptions = parse_connection_string(conninfo, &errorBuf, false);
03997 if (connOptions == NULL && errmsg)
03998 *errmsg = errorBuf.data;
03999 else
04000 termPQExpBuffer(&errorBuf);
04001 return connOptions;
04002 }
04003
04004
04005
04006
04007 static PQconninfoOption *
04008 conninfo_init(PQExpBuffer errorMessage)
04009 {
04010 PQconninfoOption *options;
04011 PQconninfoOption *opt_dest;
04012 const internalPQconninfoOption *cur_opt;
04013
04014
04015
04016
04017
04018 options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
04019 if (options == NULL)
04020 {
04021 printfPQExpBuffer(errorMessage,
04022 libpq_gettext("out of memory\n"));
04023 return NULL;
04024 }
04025 opt_dest = options;
04026
04027 for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
04028 {
04029
04030 memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
04031 opt_dest++;
04032 }
04033 MemSet(opt_dest, 0, sizeof(PQconninfoOption));
04034
04035 return options;
04036 }
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047 static PQconninfoOption *
04048 parse_connection_string(const char *connstr, PQExpBuffer errorMessage,
04049 bool use_defaults)
04050 {
04051
04052 if (uri_prefix_length(connstr) != 0)
04053 return conninfo_uri_parse(connstr, errorMessage, use_defaults);
04054
04055
04056 return conninfo_parse(connstr, errorMessage, use_defaults);
04057 }
04058
04059
04060
04061
04062
04063
04064
04065 static int
04066 uri_prefix_length(const char *connstr)
04067 {
04068 if (strncmp(connstr, uri_designator,
04069 sizeof(uri_designator) - 1) == 0)
04070 return sizeof(uri_designator) - 1;
04071
04072 if (strncmp(connstr, short_uri_designator,
04073 sizeof(short_uri_designator) - 1) == 0)
04074 return sizeof(short_uri_designator) - 1;
04075
04076 return 0;
04077 }
04078
04079
04080
04081
04082
04083
04084
04085
04086 static bool
04087 recognized_connection_string(const char *connstr)
04088 {
04089 return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
04090 }
04091
04092
04093
04094
04095
04096
04097 static PQconninfoOption *
04098 conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
04099 bool use_defaults)
04100 {
04101 char *pname;
04102 char *pval;
04103 char *buf;
04104 char *cp;
04105 char *cp2;
04106 PQconninfoOption *options;
04107
04108
04109 options = conninfo_init(errorMessage);
04110 if (options == NULL)
04111 return NULL;
04112
04113
04114 if ((buf = strdup(conninfo)) == NULL)
04115 {
04116 printfPQExpBuffer(errorMessage,
04117 libpq_gettext("out of memory\n"));
04118 PQconninfoFree(options);
04119 return NULL;
04120 }
04121 cp = buf;
04122
04123 while (*cp)
04124 {
04125
04126 if (isspace((unsigned char) *cp))
04127 {
04128 cp++;
04129 continue;
04130 }
04131
04132
04133 pname = cp;
04134 while (*cp)
04135 {
04136 if (*cp == '=')
04137 break;
04138 if (isspace((unsigned char) *cp))
04139 {
04140 *cp++ = '\0';
04141 while (*cp)
04142 {
04143 if (!isspace((unsigned char) *cp))
04144 break;
04145 cp++;
04146 }
04147 break;
04148 }
04149 cp++;
04150 }
04151
04152
04153 if (*cp != '=')
04154 {
04155 printfPQExpBuffer(errorMessage,
04156 libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
04157 pname);
04158 PQconninfoFree(options);
04159 free(buf);
04160 return NULL;
04161 }
04162 *cp++ = '\0';
04163
04164
04165 while (*cp)
04166 {
04167 if (!isspace((unsigned char) *cp))
04168 break;
04169 cp++;
04170 }
04171
04172
04173 pval = cp;
04174
04175 if (*cp != '\'')
04176 {
04177 cp2 = pval;
04178 while (*cp)
04179 {
04180 if (isspace((unsigned char) *cp))
04181 {
04182 *cp++ = '\0';
04183 break;
04184 }
04185 if (*cp == '\\')
04186 {
04187 cp++;
04188 if (*cp != '\0')
04189 *cp2++ = *cp++;
04190 }
04191 else
04192 *cp2++ = *cp++;
04193 }
04194 *cp2 = '\0';
04195 }
04196 else
04197 {
04198 cp2 = pval;
04199 cp++;
04200 for (;;)
04201 {
04202 if (*cp == '\0')
04203 {
04204 printfPQExpBuffer(errorMessage,
04205 libpq_gettext("unterminated quoted string in connection info string\n"));
04206 PQconninfoFree(options);
04207 free(buf);
04208 return NULL;
04209 }
04210 if (*cp == '\\')
04211 {
04212 cp++;
04213 if (*cp != '\0')
04214 *cp2++ = *cp++;
04215 continue;
04216 }
04217 if (*cp == '\'')
04218 {
04219 *cp2 = '\0';
04220 cp++;
04221 break;
04222 }
04223 *cp2++ = *cp++;
04224 }
04225 }
04226
04227
04228
04229
04230 if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
04231 {
04232 PQconninfoFree(options);
04233 free(buf);
04234 return NULL;
04235 }
04236 }
04237
04238
04239 free(buf);
04240
04241
04242
04243
04244 if (use_defaults)
04245 {
04246 if (!conninfo_add_defaults(options, errorMessage))
04247 {
04248 PQconninfoFree(options);
04249 return NULL;
04250 }
04251 }
04252
04253 return options;
04254 }
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270 static PQconninfoOption *
04271 conninfo_array_parse(const char *const * keywords, const char *const * values,
04272 PQExpBuffer errorMessage, bool use_defaults,
04273 int expand_dbname)
04274 {
04275 PQconninfoOption *options;
04276 PQconninfoOption *dbname_options = NULL;
04277 PQconninfoOption *option;
04278 int i = 0;
04279
04280
04281
04282
04283
04284 while (expand_dbname && keywords[i])
04285 {
04286 const char *pname = keywords[i];
04287 const char *pvalue = values[i];
04288
04289
04290 if (strcmp(pname, "dbname") == 0 && pvalue)
04291 {
04292
04293
04294
04295
04296
04297 if (recognized_connection_string(pvalue))
04298 {
04299 dbname_options = parse_connection_string(pvalue, errorMessage, false);
04300 if (dbname_options == NULL)
04301 return NULL;
04302 }
04303 break;
04304 }
04305 ++i;
04306 }
04307
04308
04309 options = conninfo_init(errorMessage);
04310 if (options == NULL)
04311 {
04312 PQconninfoFree(dbname_options);
04313 return NULL;
04314 }
04315
04316
04317 i = 0;
04318 while (keywords[i])
04319 {
04320 const char *pname = keywords[i];
04321 const char *pvalue = values[i];
04322
04323 if (pvalue != NULL)
04324 {
04325
04326 for (option = options; option->keyword != NULL; option++)
04327 {
04328 if (strcmp(option->keyword, pname) == 0)
04329 break;
04330 }
04331
04332
04333 if (option->keyword == NULL)
04334 {
04335 printfPQExpBuffer(errorMessage,
04336 libpq_gettext("invalid connection option \"%s\"\n"),
04337 pname);
04338 PQconninfoFree(options);
04339 PQconninfoFree(dbname_options);
04340 return NULL;
04341 }
04342
04343
04344
04345
04346
04347
04348 if (strcmp(pname, "dbname") == 0 && dbname_options)
04349 {
04350 PQconninfoOption *str_option;
04351
04352 for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
04353 {
04354 if (str_option->val != NULL)
04355 {
04356 int k;
04357
04358 for (k = 0; options[k].keyword; k++)
04359 {
04360 if (strcmp(options[k].keyword, str_option->keyword) == 0)
04361 {
04362 if (options[k].val)
04363 free(options[k].val);
04364 options[k].val = strdup(str_option->val);
04365 break;
04366 }
04367 }
04368 }
04369 }
04370 }
04371 else
04372 {
04373
04374
04375
04376 if (option->val)
04377 free(option->val);
04378 option->val = strdup(pvalue);
04379 if (!option->val)
04380 {
04381 printfPQExpBuffer(errorMessage,
04382 libpq_gettext("out of memory\n"));
04383 PQconninfoFree(options);
04384 PQconninfoFree(dbname_options);
04385 return NULL;
04386 }
04387 }
04388 }
04389 ++i;
04390 }
04391 PQconninfoFree(dbname_options);
04392
04393
04394
04395
04396 if (use_defaults)
04397 {
04398 if (!conninfo_add_defaults(options, errorMessage))
04399 {
04400 PQconninfoFree(options);
04401 return NULL;
04402 }
04403 }
04404
04405 return options;
04406 }
04407
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418 static bool
04419 conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
04420 {
04421 PQconninfoOption *option;
04422 char *tmp;
04423
04424
04425
04426
04427
04428 if (parseServiceInfo(options, errorMessage) != 0)
04429 return false;
04430
04431
04432
04433
04434
04435 for (option = options; option->keyword != NULL; option++)
04436 {
04437 if (option->val != NULL)
04438 continue;
04439
04440
04441
04442
04443 if (option->envvar != NULL)
04444 {
04445 if ((tmp = getenv(option->envvar)) != NULL)
04446 {
04447 option->val = strdup(tmp);
04448 if (!option->val)
04449 {
04450 printfPQExpBuffer(errorMessage,
04451 libpq_gettext("out of memory\n"));
04452 return false;
04453 }
04454 continue;
04455 }
04456 }
04457
04458
04459
04460
04461
04462 if (option->compiled != NULL)
04463 {
04464 option->val = strdup(option->compiled);
04465 if (!option->val)
04466 {
04467 printfPQExpBuffer(errorMessage,
04468 libpq_gettext("out of memory\n"));
04469 return false;
04470 }
04471 continue;
04472 }
04473
04474
04475
04476
04477 if (strcmp(option->keyword, "user") == 0)
04478 {
04479 option->val = pg_fe_getauthname(errorMessage);
04480 continue;
04481 }
04482 }
04483
04484 return true;
04485 }
04486
04487
04488
04489
04490
04491
04492 static PQconninfoOption *
04493 conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage,
04494 bool use_defaults)
04495 {
04496 PQconninfoOption *options;
04497
04498
04499 options = conninfo_init(errorMessage);
04500 if (options == NULL)
04501 return NULL;
04502
04503 if (!conninfo_uri_parse_options(options, uri, errorMessage))
04504 {
04505 PQconninfoFree(options);
04506 return NULL;
04507 }
04508
04509
04510
04511
04512 if (use_defaults)
04513 {
04514 if (!conninfo_add_defaults(options, errorMessage))
04515 {
04516 PQconninfoFree(options);
04517 return NULL;
04518 }
04519 }
04520
04521 return options;
04522 }
04523
04524
04525
04526
04527
04528
04529
04530
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541
04542 static bool
04543 conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
04544 PQExpBuffer errorMessage)
04545 {
04546 int prefix_len;
04547 char *p;
04548 char *buf = strdup(uri);
04549
04550 char *start = buf;
04551 char prevchar = '\0';
04552 char *user = NULL;
04553 char *host = NULL;
04554 bool retval = false;
04555
04556 if (buf == NULL)
04557 {
04558 printfPQExpBuffer(errorMessage,
04559 libpq_gettext("out of memory\n"));
04560 return false;
04561 }
04562
04563
04564 prefix_len = uri_prefix_length(uri);
04565 if (prefix_len == 0)
04566 {
04567
04568 printfPQExpBuffer(errorMessage,
04569 libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"),
04570 uri);
04571 goto cleanup;
04572 }
04573 start += prefix_len;
04574 p = start;
04575
04576
04577 while (*p && *p != '@' && *p != '/')
04578 ++p;
04579 if (*p == '@')
04580 {
04581
04582
04583
04584
04585 user = start;
04586
04587 p = user;
04588 while (*p != ':' && *p != '@')
04589 ++p;
04590
04591
04592 prevchar = *p;
04593 *p = '\0';
04594
04595 if (*user &&
04596 !conninfo_storeval(options, "user", user,
04597 errorMessage, false, true))
04598 goto cleanup;
04599
04600 if (prevchar == ':')
04601 {
04602 const char *password = p + 1;
04603
04604 while (*p != '@')
04605 ++p;
04606 *p = '\0';
04607
04608 if (*password &&
04609 !conninfo_storeval(options, "password", password,
04610 errorMessage, false, true))
04611 goto cleanup;
04612 }
04613
04614
04615 ++p;
04616 }
04617 else
04618 {
04619
04620
04621
04622 p = start;
04623 }
04624
04625
04626
04627
04628
04629
04630
04631 if (*p == '[')
04632 {
04633 host = ++p;
04634 while (*p && *p != ']')
04635 ++p;
04636 if (!*p)
04637 {
04638 printfPQExpBuffer(errorMessage,
04639 libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"),
04640 uri);
04641 goto cleanup;
04642 }
04643 if (p == host)
04644 {
04645 printfPQExpBuffer(errorMessage,
04646 libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"),
04647 uri);
04648 goto cleanup;
04649 }
04650
04651
04652 *(p++) = '\0';
04653
04654
04655
04656
04657
04658 if (*p && *p != ':' && *p != '/' && *p != '?')
04659 {
04660 printfPQExpBuffer(errorMessage,
04661 libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"),
04662 *p, (int) (p - buf + 1), uri);
04663 goto cleanup;
04664 }
04665 }
04666 else
04667 {
04668
04669 host = p;
04670
04671
04672
04673
04674
04675 while (*p && *p != ':' && *p != '/' && *p != '?')
04676 ++p;
04677 }
04678
04679
04680 prevchar = *p;
04681 *p = '\0';
04682
04683 if (*host &&
04684 !conninfo_storeval(options, "host", host,
04685 errorMessage, false, true))
04686 goto cleanup;
04687
04688
04689 if (prevchar == ':')
04690 {
04691 const char *port = ++p;
04692
04693 while (*p && *p != '/' && *p != '?')
04694 ++p;
04695
04696 prevchar = *p;
04697 *p = '\0';
04698
04699 if (*port &&
04700 !conninfo_storeval(options, "port", port,
04701 errorMessage, false, true))
04702 goto cleanup;
04703 }
04704
04705 if (prevchar && prevchar != '?')
04706 {
04707 const char *dbname = ++p;
04708
04709
04710 while (*p && *p != '?')
04711 ++p;
04712
04713 prevchar = *p;
04714 *p = '\0';
04715
04716
04717
04718
04719
04720
04721 if (*dbname &&
04722 !conninfo_storeval(options, "dbname", dbname,
04723 errorMessage, false, true))
04724 goto cleanup;
04725 }
04726
04727 if (prevchar)
04728 {
04729 ++p;
04730
04731 if (!conninfo_uri_parse_params(p, options, errorMessage))
04732 goto cleanup;
04733 }
04734
04735
04736 retval = true;
04737
04738 cleanup:
04739 free(buf);
04740 return retval;
04741 }
04742
04743
04744
04745
04746
04747
04748
04749
04750
04751 static bool
04752 conninfo_uri_parse_params(char *params,
04753 PQconninfoOption *connOptions,
04754 PQExpBuffer errorMessage)
04755 {
04756 while (*params)
04757 {
04758 char *keyword = params;
04759 char *value = NULL;
04760 char *p = params;
04761 bool malloced = false;
04762
04763
04764
04765
04766
04767 for (;;)
04768 {
04769 if (*p == '=')
04770 {
04771
04772 if (value != NULL)
04773 {
04774 printfPQExpBuffer(errorMessage,
04775 libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
04776 params);
04777 return false;
04778 }
04779
04780 *p = '\0';
04781 value = ++p;
04782 }
04783 else if (*p == '&' || *p == '\0')
04784 {
04785 char prevchar;
04786
04787
04788 prevchar = *p;
04789 *p = '\0';
04790
04791
04792 if (value == NULL)
04793 {
04794 printfPQExpBuffer(errorMessage,
04795 libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
04796 params);
04797 return false;
04798 }
04799
04800
04801
04802
04803
04804 if (prevchar != '\0')
04805 ++p;
04806 break;
04807 }
04808
04809
04810 ++p;
04811 }
04812
04813 keyword = conninfo_uri_decode(keyword, errorMessage);
04814 if (keyword == NULL)
04815 {
04816
04817 return false;
04818 }
04819 value = conninfo_uri_decode(value, errorMessage);
04820 if (value == NULL)
04821 {
04822
04823 free(keyword);
04824 return false;
04825 }
04826 malloced = true;
04827
04828
04829
04830
04831 if (strcmp(keyword, "ssl") == 0 &&
04832 strcmp(value, "true") == 0)
04833 {
04834 free(keyword);
04835 free(value);
04836 malloced = false;
04837
04838 keyword = "sslmode";
04839 value = "require";
04840 }
04841
04842
04843
04844
04845
04846
04847 if (!conninfo_storeval(connOptions, keyword, value,
04848 errorMessage, true, false))
04849 {
04850
04851
04852
04853
04854 if (errorMessage->len != 0)
04855 {
04856 if (malloced)
04857 {
04858 free(keyword);
04859 free(value);
04860 }
04861 return false;
04862 }
04863
04864 printfPQExpBuffer(errorMessage,
04865 libpq_gettext(
04866 "invalid URI query parameter: \"%s\"\n"),
04867 keyword);
04868 if (malloced)
04869 {
04870 free(keyword);
04871 free(value);
04872 }
04873 return false;
04874 }
04875 if (malloced)
04876 {
04877 free(keyword);
04878 free(value);
04879 }
04880
04881
04882 params = p;
04883 }
04884
04885 return true;
04886 }
04887
04888
04889
04890
04891
04892
04893
04894
04895
04896
04897
04898
04899
04900 static char *
04901 conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
04902 {
04903 char *buf = malloc(strlen(str) + 1);
04904 char *p = buf;
04905 const char *q = str;
04906
04907 if (buf == NULL)
04908 {
04909 printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
04910 return NULL;
04911 }
04912
04913 for (;;)
04914 {
04915 if (*q != '%')
04916 {
04917
04918 if (!(*(p++) = *(q++)))
04919 break;
04920 }
04921 else
04922 {
04923 int hi;
04924 int lo;
04925 int c;
04926
04927 ++q;
04928
04929
04930
04931
04932
04933 if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
04934 {
04935 printfPQExpBuffer(errorMessage,
04936 libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
04937 str);
04938 free(buf);
04939 return NULL;
04940 }
04941
04942 c = (hi << 4) | lo;
04943 if (c == 0)
04944 {
04945 printfPQExpBuffer(errorMessage,
04946 libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
04947 str);
04948 free(buf);
04949 return NULL;
04950 }
04951 *(p++) = c;
04952 }
04953 }
04954
04955 return buf;
04956 }
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966 static bool
04967 get_hexdigit(char digit, int *value)
04968 {
04969 if ('0' <= digit && digit <= '9')
04970 *value = digit - '0';
04971 else if ('A' <= digit && digit <= 'F')
04972 *value = digit - 'A' + 10;
04973 else if ('a' <= digit && digit <= 'f')
04974 *value = digit - 'a' + 10;
04975 else
04976 return false;
04977
04978 return true;
04979 }
04980
04981
04982
04983
04984
04985
04986
04987 static const char *
04988 conninfo_getval(PQconninfoOption *connOptions,
04989 const char *keyword)
04990 {
04991 PQconninfoOption *option;
04992
04993 option = conninfo_find(connOptions, keyword);
04994
04995 return option ? option->val : NULL;
04996 }
04997
04998
04999
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009
05010
05011
05012
05013 static PQconninfoOption *
05014 conninfo_storeval(PQconninfoOption *connOptions,
05015 const char *keyword, const char *value,
05016 PQExpBuffer errorMessage, bool ignoreMissing,
05017 bool uri_decode)
05018 {
05019 PQconninfoOption *option;
05020 char *value_copy;
05021
05022
05023
05024
05025
05026
05027 if (strcmp(keyword, "requiressl") == 0)
05028 {
05029 keyword = "sslmode";
05030 if (value[0] == '1')
05031 value = "require";
05032 else
05033 value = "prefer";
05034 }
05035
05036 option = conninfo_find(connOptions, keyword);
05037 if (option == NULL)
05038 {
05039 if (!ignoreMissing)
05040 printfPQExpBuffer(errorMessage,
05041 libpq_gettext("invalid connection option \"%s\"\n"),
05042 keyword);
05043 return NULL;
05044 }
05045
05046 if (uri_decode)
05047 {
05048 value_copy = conninfo_uri_decode(value, errorMessage);
05049 if (value_copy == NULL)
05050
05051 return NULL;
05052 }
05053 else
05054 {
05055 value_copy = strdup(value);
05056
05057 if (value_copy == NULL)
05058 {
05059 printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
05060 return NULL;
05061 }
05062 }
05063
05064 if (option->val)
05065 free(option->val);
05066 option->val = value_copy;
05067
05068 return option;
05069 }
05070
05071
05072
05073
05074
05075
05076
05077
05078
05079 static PQconninfoOption *
05080 conninfo_find(PQconninfoOption *connOptions, const char *keyword)
05081 {
05082 PQconninfoOption *option;
05083
05084 for (option = connOptions; option->keyword != NULL; option++)
05085 {
05086 if (strcmp(option->keyword, keyword) == 0)
05087 return option;
05088 }
05089
05090 return NULL;
05091 }
05092
05093
05094
05095
05096
05097 PQconninfoOption *
05098 PQconninfo(PGconn *conn)
05099 {
05100 PQExpBufferData errorBuf;
05101 PQconninfoOption *connOptions;
05102
05103 if (conn == NULL)
05104 return NULL;
05105
05106
05107 initPQExpBuffer(&errorBuf);
05108 if (PQExpBufferDataBroken(errorBuf))
05109 return NULL;
05110
05111 connOptions = conninfo_init(&errorBuf);
05112
05113 if (connOptions != NULL)
05114 {
05115 const internalPQconninfoOption *option;
05116
05117 for (option = PQconninfoOptions; option->keyword; option++)
05118 {
05119 char **connmember;
05120
05121 if (option->connofs < 0)
05122 continue;
05123
05124 connmember = (char **) ((char *) conn + option->connofs);
05125
05126 if (*connmember)
05127 conninfo_storeval(connOptions, option->keyword, *connmember,
05128 &errorBuf, true, false);
05129 }
05130 }
05131
05132 termPQExpBuffer(&errorBuf);
05133
05134 return connOptions;
05135 }
05136
05137
05138 void
05139 PQconninfoFree(PQconninfoOption *connOptions)
05140 {
05141 PQconninfoOption *option;
05142
05143 if (connOptions == NULL)
05144 return;
05145
05146 for (option = connOptions; option->keyword != NULL; option++)
05147 {
05148 if (option->val != NULL)
05149 free(option->val);
05150 }
05151 free(connOptions);
05152 }
05153
05154
05155
05156 char *
05157 PQdb(const PGconn *conn)
05158 {
05159 if (!conn)
05160 return NULL;
05161 return conn->dbName;
05162 }
05163
05164 char *
05165 PQuser(const PGconn *conn)
05166 {
05167 if (!conn)
05168 return NULL;
05169 return conn->pguser;
05170 }
05171
05172 char *
05173 PQpass(const PGconn *conn)
05174 {
05175 if (!conn)
05176 return NULL;
05177 return conn->pgpass;
05178 }
05179
05180 char *
05181 PQhost(const PGconn *conn)
05182 {
05183 if (!conn)
05184 return NULL;
05185 return conn->pghost ? conn->pghost : conn->pgunixsocket;
05186 }
05187
05188 char *
05189 PQport(const PGconn *conn)
05190 {
05191 if (!conn)
05192 return NULL;
05193 return conn->pgport;
05194 }
05195
05196 char *
05197 PQtty(const PGconn *conn)
05198 {
05199 if (!conn)
05200 return NULL;
05201 return conn->pgtty;
05202 }
05203
05204 char *
05205 PQoptions(const PGconn *conn)
05206 {
05207 if (!conn)
05208 return NULL;
05209 return conn->pgoptions;
05210 }
05211
05212 ConnStatusType
05213 PQstatus(const PGconn *conn)
05214 {
05215 if (!conn)
05216 return CONNECTION_BAD;
05217 return conn->status;
05218 }
05219
05220 PGTransactionStatusType
05221 PQtransactionStatus(const PGconn *conn)
05222 {
05223 if (!conn || conn->status != CONNECTION_OK)
05224 return PQTRANS_UNKNOWN;
05225 if (conn->asyncStatus != PGASYNC_IDLE)
05226 return PQTRANS_ACTIVE;
05227 return conn->xactStatus;
05228 }
05229
05230 const char *
05231 PQparameterStatus(const PGconn *conn, const char *paramName)
05232 {
05233 const pgParameterStatus *pstatus;
05234
05235 if (!conn || !paramName)
05236 return NULL;
05237 for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
05238 {
05239 if (strcmp(pstatus->name, paramName) == 0)
05240 return pstatus->value;
05241 }
05242 return NULL;
05243 }
05244
05245 int
05246 PQprotocolVersion(const PGconn *conn)
05247 {
05248 if (!conn)
05249 return 0;
05250 if (conn->status == CONNECTION_BAD)
05251 return 0;
05252 return PG_PROTOCOL_MAJOR(conn->pversion);
05253 }
05254
05255 int
05256 PQserverVersion(const PGconn *conn)
05257 {
05258 if (!conn)
05259 return 0;
05260 if (conn->status == CONNECTION_BAD)
05261 return 0;
05262 return conn->sversion;
05263 }
05264
05265 char *
05266 PQerrorMessage(const PGconn *conn)
05267 {
05268 if (!conn)
05269 return libpq_gettext("connection pointer is NULL\n");
05270
05271 return conn->errorMessage.data;
05272 }
05273
05274 int
05275 PQsocket(const PGconn *conn)
05276 {
05277 if (!conn)
05278 return -1;
05279 return conn->sock;
05280 }
05281
05282 int
05283 PQbackendPID(const PGconn *conn)
05284 {
05285 if (!conn || conn->status != CONNECTION_OK)
05286 return 0;
05287 return conn->be_pid;
05288 }
05289
05290 int
05291 PQconnectionNeedsPassword(const PGconn *conn)
05292 {
05293 if (!conn)
05294 return false;
05295 if (conn->password_needed &&
05296 (conn->pgpass == NULL || conn->pgpass[0] == '\0'))
05297 return true;
05298 else
05299 return false;
05300 }
05301
05302 int
05303 PQconnectionUsedPassword(const PGconn *conn)
05304 {
05305 if (!conn)
05306 return false;
05307 if (conn->password_needed)
05308 return true;
05309 else
05310 return false;
05311 }
05312
05313 int
05314 PQclientEncoding(const PGconn *conn)
05315 {
05316 if (!conn || conn->status != CONNECTION_OK)
05317 return -1;
05318 return conn->client_encoding;
05319 }
05320
05321 int
05322 PQsetClientEncoding(PGconn *conn, const char *encoding)
05323 {
05324 char qbuf[128];
05325 static const char query[] = "set client_encoding to '%s'";
05326 PGresult *res;
05327 int status;
05328
05329 if (!conn || conn->status != CONNECTION_OK)
05330 return -1;
05331
05332 if (!encoding)
05333 return -1;
05334
05335
05336 if (strcmp(encoding, "auto") == 0)
05337 encoding = pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true));
05338
05339
05340 if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
05341 return -1;
05342
05343
05344 sprintf(qbuf, query, encoding);
05345 res = PQexec(conn, qbuf);
05346
05347 if (res == NULL)
05348 return -1;
05349 if (res->resultStatus != PGRES_COMMAND_OK)
05350 status = -1;
05351 else
05352 {
05353
05354
05355
05356
05357
05358
05359 if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
05360 pqSaveParameterStatus(conn, "client_encoding", encoding);
05361 status = 0;
05362 }
05363 PQclear(res);
05364 return status;
05365 }
05366
05367 PGVerbosity
05368 PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
05369 {
05370 PGVerbosity old;
05371
05372 if (!conn)
05373 return PQERRORS_DEFAULT;
05374 old = conn->verbosity;
05375 conn->verbosity = verbosity;
05376 return old;
05377 }
05378
05379 void
05380 PQtrace(PGconn *conn, FILE *debug_port)
05381 {
05382 if (conn == NULL)
05383 return;
05384 PQuntrace(conn);
05385 conn->Pfdebug = debug_port;
05386 }
05387
05388 void
05389 PQuntrace(PGconn *conn)
05390 {
05391 if (conn == NULL)
05392 return;
05393 if (conn->Pfdebug)
05394 {
05395 fflush(conn->Pfdebug);
05396 conn->Pfdebug = NULL;
05397 }
05398 }
05399
05400 PQnoticeReceiver
05401 PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg)
05402 {
05403 PQnoticeReceiver old;
05404
05405 if (conn == NULL)
05406 return NULL;
05407
05408 old = conn->noticeHooks.noticeRec;
05409 if (proc)
05410 {
05411 conn->noticeHooks.noticeRec = proc;
05412 conn->noticeHooks.noticeRecArg = arg;
05413 }
05414 return old;
05415 }
05416
05417 PQnoticeProcessor
05418 PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
05419 {
05420 PQnoticeProcessor old;
05421
05422 if (conn == NULL)
05423 return NULL;
05424
05425 old = conn->noticeHooks.noticeProc;
05426 if (proc)
05427 {
05428 conn->noticeHooks.noticeProc = proc;
05429 conn->noticeHooks.noticeProcArg = arg;
05430 }
05431 return old;
05432 }
05433
05434
05435
05436
05437
05438
05439
05440 static void
05441 defaultNoticeReceiver(void *arg, const PGresult *res)
05442 {
05443 (void) arg;
05444 if (res->noticeHooks.noticeProc != NULL)
05445 (*res->noticeHooks.noticeProc) (res->noticeHooks.noticeProcArg,
05446 PQresultErrorMessage(res));
05447 }
05448
05449
05450
05451
05452
05453
05454
05455 static void
05456 defaultNoticeProcessor(void *arg, const char *message)
05457 {
05458 (void) arg;
05459
05460 fprintf(stderr, "%s", message);
05461 }
05462
05463
05464
05465
05466
05467 static char *
05468 pwdfMatchesString(char *buf, char *token)
05469 {
05470 char *tbuf,
05471 *ttok;
05472 bool bslash = false;
05473
05474 if (buf == NULL || token == NULL)
05475 return NULL;
05476 tbuf = buf;
05477 ttok = token;
05478 if (tbuf[0] == '*' && tbuf[1] == ':')
05479 return tbuf + 2;
05480 while (*tbuf != 0)
05481 {
05482 if (*tbuf == '\\' && !bslash)
05483 {
05484 tbuf++;
05485 bslash = true;
05486 }
05487 if (*tbuf == ':' && *ttok == 0 && !bslash)
05488 return tbuf + 1;
05489 bslash = false;
05490 if (*ttok == 0)
05491 return NULL;
05492 if (*tbuf == *ttok)
05493 {
05494 tbuf++;
05495 ttok++;
05496 }
05497 else
05498 return NULL;
05499 }
05500 return NULL;
05501 }
05502
05503
05504 static char *
05505 PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
05506 {
05507 FILE *fp;
05508 char pgpassfile[MAXPGPATH];
05509 struct stat stat_buf;
05510
05511 #define LINELEN NAMEDATALEN*5
05512 char buf[LINELEN];
05513
05514 if (dbname == NULL || strlen(dbname) == 0)
05515 return NULL;
05516
05517 if (username == NULL || strlen(username) == 0)
05518 return NULL;
05519
05520
05521 if (hostname == NULL)
05522 hostname = DefaultHost;
05523 else if (is_absolute_path(hostname))
05524
05525
05526
05527
05528
05529 if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
05530 hostname = DefaultHost;
05531
05532 if (port == NULL)
05533 port = DEF_PGPORT_STR;
05534
05535 if (!getPgPassFilename(pgpassfile))
05536 return NULL;
05537
05538
05539 if (stat(pgpassfile, &stat_buf) != 0)
05540 return NULL;
05541
05542 #ifndef WIN32
05543 if (!S_ISREG(stat_buf.st_mode))
05544 {
05545 fprintf(stderr,
05546 libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
05547 pgpassfile);
05548 return NULL;
05549 }
05550
05551
05552 if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
05553 {
05554 fprintf(stderr,
05555 libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
05556 pgpassfile);
05557 return NULL;
05558 }
05559 #else
05560
05561
05562
05563
05564
05565 #endif
05566
05567 fp = fopen(pgpassfile, "r");
05568 if (fp == NULL)
05569 return NULL;
05570
05571 while (!feof(fp) && !ferror(fp))
05572 {
05573 char *t = buf,
05574 *ret,
05575 *p1,
05576 *p2;
05577 int len;
05578
05579 if (fgets(buf, sizeof(buf), fp) == NULL)
05580 break;
05581
05582 len = strlen(buf);
05583 if (len == 0)
05584 continue;
05585
05586
05587 if (buf[len - 1] == '\n')
05588 buf[len - 1] = 0;
05589
05590 if ((t = pwdfMatchesString(t, hostname)) == NULL ||
05591 (t = pwdfMatchesString(t, port)) == NULL ||
05592 (t = pwdfMatchesString(t, dbname)) == NULL ||
05593 (t = pwdfMatchesString(t, username)) == NULL)
05594 continue;
05595 ret = strdup(t);
05596 fclose(fp);
05597
05598
05599 for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
05600 {
05601 if (*p1 == '\\' && p1[1] != '\0')
05602 ++p1;
05603 *p2 = *p1;
05604 }
05605 *p2 = '\0';
05606
05607 return ret;
05608 }
05609
05610 fclose(fp);
05611 return NULL;
05612
05613 #undef LINELEN
05614 }
05615
05616
05617 static bool
05618 getPgPassFilename(char *pgpassfile)
05619 {
05620 char *passfile_env;
05621
05622 if ((passfile_env = getenv("PGPASSFILE")) != NULL)
05623
05624 strlcpy(pgpassfile, passfile_env, MAXPGPATH);
05625 else
05626 {
05627 char homedir[MAXPGPATH];
05628
05629 if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
05630 return false;
05631 snprintf(pgpassfile, MAXPGPATH, "%s/%s", homedir, PGPASSFILE);
05632 }
05633 return true;
05634 }
05635
05636
05637
05638
05639
05640
05641 static void
05642 dot_pg_pass_warning(PGconn *conn)
05643 {
05644
05645
05646 if (conn->dot_pgpass_used && conn->password_needed && conn->result &&
05647 strcmp(PQresultErrorField(conn->result, PG_DIAG_SQLSTATE),
05648 ERRCODE_INVALID_PASSWORD) == 0)
05649 {
05650 char pgpassfile[MAXPGPATH];
05651
05652 if (!getPgPassFilename(pgpassfile))
05653 return;
05654 appendPQExpBuffer(&conn->errorMessage,
05655 libpq_gettext("password retrieved from file \"%s\"\n"),
05656 pgpassfile);
05657 }
05658 }
05659
05660
05661
05662
05663
05664
05665
05666
05667
05668
05669
05670
05671 bool
05672 pqGetHomeDirectory(char *buf, int bufsize)
05673 {
05674 #ifndef WIN32
05675 char pwdbuf[BUFSIZ];
05676 struct passwd pwdstr;
05677 struct passwd *pwd = NULL;
05678
05679 if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) != 0)
05680 return false;
05681 strlcpy(buf, pwd->pw_dir, bufsize);
05682 return true;
05683 #else
05684 char tmppath[MAX_PATH];
05685
05686 ZeroMemory(tmppath, sizeof(tmppath));
05687 if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
05688 return false;
05689 snprintf(buf, bufsize, "%s/postgresql", tmppath);
05690 return true;
05691 #endif
05692 }
05693
05694
05695
05696
05697
05698
05699 static void
05700 default_threadlock(int acquire)
05701 {
05702 #ifdef ENABLE_THREAD_SAFETY
05703 #ifndef WIN32
05704 static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
05705 #else
05706 static pthread_mutex_t singlethread_lock = NULL;
05707 static long mutex_initlock = 0;
05708
05709 if (singlethread_lock == NULL)
05710 {
05711 while (InterlockedExchange(&mutex_initlock, 1) == 1)
05712 ;
05713 if (singlethread_lock == NULL)
05714 {
05715 if (pthread_mutex_init(&singlethread_lock, NULL))
05716 PGTHREAD_ERROR("failed to initialize mutex");
05717 }
05718 InterlockedExchange(&mutex_initlock, 0);
05719 }
05720 #endif
05721 if (acquire)
05722 {
05723 if (pthread_mutex_lock(&singlethread_lock))
05724 PGTHREAD_ERROR("failed to lock mutex");
05725 }
05726 else
05727 {
05728 if (pthread_mutex_unlock(&singlethread_lock))
05729 PGTHREAD_ERROR("failed to unlock mutex");
05730 }
05731 #endif
05732 }
05733
05734 pgthreadlock_t
05735 PQregisterThreadLock(pgthreadlock_t newhandler)
05736 {
05737 pgthreadlock_t prev = pg_g_threadlock;
05738
05739 if (newhandler)
05740 pg_g_threadlock = newhandler;
05741 else
05742 pg_g_threadlock = default_threadlock;
05743
05744 return prev;
05745 }