📄 fe-auth.c
字号:
/*------------------------------------------------------------------------- * * fe-auth.c * The front-end (client) authorization routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.29 1999/05/25 16:15:10 momjian Exp $ * *------------------------------------------------------------------------- *//* * INTERFACE ROUTINES * frontend (client) routines: * fe_sendauth send authentication information * fe_getauthname get user's name according to the client side * of the authentication system * fe_setauthsvc set frontend authentication service * fe_getauthsvc get current frontend authentication service * * * */#include "libpq-fe.h"#include "libpq-int.h"#include "fe-auth.h"#include "postgres.h"#ifdef WIN32#include "win32.h"#else#include <string.h>#include <sys/param.h> /* for MAXHOSTNAMELEN on most */#ifndef MAXHOSTNAMELEN#include <netdb.h> /* for MAXHOSTNAMELEN on some */#endif#if !defined(NO_UNISTD_H)#include <unistd.h>#endif#include <pwd.h>#endif /* WIN32 */#ifdef HAVE_CRYPT_H#include <crypt.h>#endif/*---------------------------------------------------------------- * common definitions for generic fe/be routines *---------------------------------------------------------------- */struct authsvc{ char name[NAMEDATALEN]; /* service nickname (for command * line) */ MsgType msgtype; /* startup packet header type */ int allowed; /* initially allowed (before command line * option parsing)? */};/* * Command-line parsing routines use this structure to map nicknames * onto service types (and the startup packets to use with them). * * Programs receiving an authentication request use this structure to * decide which authentication service types are currently permitted. * By default, all authentication systems compiled into the system are * allowed. Unauthenticated connections are disallowed unless there * isn't any authentication system. */static struct authsvc authsvcs[] = {#ifdef KRB4 {"krb4", STARTUP_KRB4_MSG, 1}, {"kerberos", STARTUP_KRB4_MSG, 1},#endif /* KRB4 */#ifdef KRB5 {"krb5", STARTUP_KRB5_MSG, 1}, {"kerberos", STARTUP_KRB5_MSG, 1},#endif /* KRB5 */ {UNAUTHNAME, STARTUP_MSG,#if defined(KRB4) || defined(KRB5) 0#else /* !(KRB4 || KRB5) */ 1#endif /* !(KRB4 || KRB5) */ }, {"password", STARTUP_PASSWORD_MSG, 0}};static int n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc);#ifdef KRB4/*---------------------------------------------------------------- * MIT Kerberos authentication system - protocol version 4 *---------------------------------------------------------------- */#include "krb.h"/* for some reason, this is not defined in krb.h ... */extern char *tkt_string(void);/* * pg_krb4_init -- initialization performed before any Kerberos calls are made * * For v4, all we need to do is make sure the library routines get the right * ticket file if we want them to see a special one. (They will open the file * themselves.) */static voidpg_krb4_init(){ char *realm; static init_done = 0; if (init_done) return; init_done = 1; /* * If the user set PGREALM, then we use a ticket file with a special * name: <usual-ticket-file-name>@<PGREALM-value> */ if (realm = getenv("PGREALM")) { char tktbuf[MAXPATHLEN]; (void) sprintf(tktbuf, "%s@%s", tkt_string(), realm); krb_set_tkt_string(tktbuf); }}/* * pg_krb4_authname -- returns a pointer to static space containing whatever * name the user has authenticated to the system * * We obtain this information by digging around in the ticket file. */static char *pg_krb4_authname(char *PQerrormsg){ char instance[INST_SZ + 1]; char realm[REALM_SZ + 1]; int status; static char name[SNAME_SZ + 1] = ""; if (name[0]) return name; pg_krb4_init(); name[SNAME_SZ] = '\0'; status = krb_get_tf_fullname(tkt_string(), name, instance, realm); if (status != KSUCCESS) { (void) sprintf(PQerrormsg, "pg_krb4_authname: krb_get_tf_fullname: %s\n", krb_err_txt[status]); return (char *) NULL; } return name;}/* * pg_krb4_sendauth -- client routine to send authentication information to * the server * * This routine does not do mutual authentication, nor does it return enough * information to do encrypted connections. But then, if we want to do * encrypted connections, we'll have to redesign the whole RPC mechanism * anyway. * * If the user is too lazy to feed us a hostname, we try to come up with * something other than "localhost" since the hostname is used as an * instance and instance names in v4 databases are usually actual hostnames * (canonicalized to omit all domain suffixes). */static intpg_krb4_sendauth(const char *PQerrormsg, int sock, struct sockaddr_in * laddr, struct sockaddr_in * raddr, const char *hostname){ long krbopts = 0; /* one-way authentication */ KTEXT_ST clttkt; int status; char hostbuf[MAXHOSTNAMELEN]; const char *realm = getenv("PGREALM"); /* NULL == current realm */ if (!hostname || !(*hostname)) { if (gethostname(hostbuf, MAXHOSTNAMELEN) < 0) strcpy(hostbuf, "localhost"); hostname = hostbuf; } pg_krb4_init(); status = krb_sendauth(krbopts, sock, &clttkt, PG_KRB_SRVNAM, hostname, realm, (u_long) 0, (MSG_DAT *) NULL, (CREDENTIALS *) NULL, (Key_schedule *) NULL, laddr, raddr, PG_KRB4_VERSION); if (status != KSUCCESS) { (void) sprintf(PQerrormsg, "pg_krb4_sendauth: kerberos error: %s\n", krb_err_txt[status]); return STATUS_ERROR; } return STATUS_OK;}#endif /* KRB4 */#ifdef KRB5/*---------------------------------------------------------------- * MIT Kerberos authentication system - protocol version 5 *---------------------------------------------------------------- */#include "krb5/krb5.h"/* * pg_an_to_ln -- return the local name corresponding to an authentication * name * * XXX Assumes that the first aname component is the user name. This is NOT * necessarily so, since an aname can actually be something out of your * worst X.400 nightmare, like * ORGANIZATION=U. C. Berkeley/NAME=Paul M. Aoki@CS.BERKELEY.EDU * Note that the MIT an_to_ln code does the same thing if you don't * provide an aname mapping database...it may be a better idea to use * krb5_an_to_ln, except that it punts if multiple components are found, * and we can't afford to punt. */static char *pg_an_to_ln(const char *aname){ char *p; if ((p = strchr(aname, '/')) || (p = strchr(aname, '@'))) *p = '\0'; return aname;}/* * pg_krb5_init -- initialization performed before any Kerberos calls are made * * With v5, we can no longer set the ticket (credential cache) file name; * we now have to provide a file handle for the open (well, "resolved") * ticket file everywhere. * */static int krb5_ccachepg_krb5_init(void){ krb5_error_code code; char *realm, *defname; char tktbuf[MAXPATHLEN]; static krb5_ccache ccache = (krb5_ccache) NULL; if (ccache) return ccache; /* * If the user set PGREALM, then we use a ticket file with a special * name: <usual-ticket-file-name>@<PGREALM-value> */ if (!(defname = krb5_cc_default_name())) { (void) sprintf(PQerrormsg, "pg_krb5_init: krb5_cc_default_name failed\n"); return (krb5_ccache) NULL; } strcpy(tktbuf, defname); if (realm = getenv("PGREALM")) { strcat(tktbuf, "@"); strcat(tktbuf, realm); } if (code = krb5_cc_resolve(tktbuf, &ccache)) { (void) sprintf(PQerrormsg, "pg_krb5_init: Kerberos error %d in krb5_cc_resolve\n", code); com_err("pg_krb5_init", code, "in krb5_cc_resolve"); return (krb5_ccache) NULL; } return ccache;}/* * pg_krb5_authname -- returns a pointer to static space containing whatever * name the user has authenticated to the system * * We obtain this information by digging around in the ticket file. */static const char *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -