mirror of
https://github.com/postgres/postgres.git
synced 2025-06-02 00:01:40 -04:00
Authentication improvements:
A new pg_hba.conf column, USER Allow specifiction of lists of users separated by commas Allow group names specified by + Allow include files containing lists of users specified by @ Allow lists of databases, and database files Allow samegroup in database column to match group name matching dbname Removal of secondary password files Remove pg_passwd utility Lots of code cleanup in user.c and hba.c New data/global/pg_pwd format New data/global/pg_group file
This commit is contained in:
parent
af10378ab0
commit
43a3543a4e
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.33 2002/03/22 19:20:06 petere Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.34 2002/04/04 04:25:44 momjian Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter id="client-authentication">
|
<chapter id="client-authentication">
|
||||||
@ -10,14 +10,13 @@ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.33 2002/03/22 19:20:06
|
|||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When a client application connects to the database server, it specifies which
|
When a client application connects to the database server, it
|
||||||
<productname>PostgreSQL</productname> user name it wants to connect as,
|
specifies which <productname>PostgreSQL</productname> user name it
|
||||||
much the same way one logs into a Unix computer as a particular user.
|
wants to connect as, much the same way one logs into a Unix computer
|
||||||
Within the SQL environment the active
|
as a particular user. Within the SQL environment the active database
|
||||||
database user name determines access privileges to database
|
user name determines access privileges to database objects -- see
|
||||||
objects -- see <xref linkend="user-manag"> for more information
|
<xref linkend="user-manag"> for more information. Therefore, it is
|
||||||
about that. It is therefore obviously essential to restrict which
|
essential to restrict which database users can connect.
|
||||||
database user name(s) a given client can connect as.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -30,20 +29,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.33 2002/03/22 19:20:06
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
<productname>PostgreSQL</productname> offers a number of different
|
<productname>PostgreSQL</productname> offers a number of different
|
||||||
client authentication methods. The method to be used can be selected
|
client authentication methods. The method to be used can be selected
|
||||||
on the basis of (client) host and database; some authentication methods
|
on the basis of (client) host, database, and user.
|
||||||
allow you to restrict by user name as well.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<productname>PostgreSQL</productname> database user names are logically
|
<productname>PostgreSQL</productname> user names are logically
|
||||||
separate from user names of the operating system in which the server
|
separate from user names of the operating system in which the server
|
||||||
runs. If all the users of a particular server also have accounts on
|
runs. If all the users of a particular server also have accounts on
|
||||||
the server's machine, it makes sense to assign database user names
|
the server's machine, it makes sense to assign database user names
|
||||||
that match their operating system user names. However, a server that accepts remote
|
that match their operating system user names. However, a server that
|
||||||
connections may have many users who have no local account, and in such
|
accepts remote connections may have many users who have no local
|
||||||
cases there need be no connection between database user names and OS
|
account, and in such cases there need be no connection between
|
||||||
user names.
|
database user names and OS user names.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect1 id="pg-hba-conf">
|
<sect1 id="pg-hba-conf">
|
||||||
@ -56,39 +54,39 @@ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.33 2002/03/22 19:20:06
|
|||||||
<para>
|
<para>
|
||||||
Client authentication is controlled by the file
|
Client authentication is controlled by the file
|
||||||
<filename>pg_hba.conf</filename> in the data directory, e.g.,
|
<filename>pg_hba.conf</filename> in the data directory, e.g.,
|
||||||
<filename>/usr/local/pgsql/data/pg_hba.conf</filename>. (<acronym>HBA</> stands
|
<filename>/usr/local/pgsql/data/pg_hba.conf</filename>.
|
||||||
for host-based authentication.) A default <filename>pg_hba.conf</filename>
|
(<acronym>HBA</> stands for host-based authentication.) A default
|
||||||
file is installed when the
|
<filename>pg_hba.conf</filename> file is installed when the data area
|
||||||
data area is initialized by <command>initdb</command>.
|
is initialized by <command>initdb</command>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The general format of the <filename>pg_hba.conf</filename> file is
|
The general format of the <filename>pg_hba.conf</filename> file is of
|
||||||
of a set of records, one per line. Blank lines and lines beginning
|
a set of records, one per line. Blank lines are ignored, as is any
|
||||||
with a hash character (<quote>#</quote>) are ignored. A record is
|
text after the <quote>#</quote> comment character. A record is made
|
||||||
made up of a number of fields which are separated by spaces and/or
|
up of a number of fields which are separated by spaces and/or tabs.
|
||||||
tabs. Records cannot be continued across lines.
|
Fields can contain white space if the field value is quoted. Records
|
||||||
|
cannot be continued across lines.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Each record specifies a connection type, a client IP address range
|
Each record specifies a connection type, a client IP address range
|
||||||
(if relevant for the connection type), a database name or names,
|
(if relevant for the connection type), a database name, a user name,
|
||||||
and the authentication method to be used for connections matching
|
and the authentication method to be used for connections matching
|
||||||
these parameters.
|
these parameters. The first record with a matching connection type,
|
||||||
The first record that matches the type, client address, and requested
|
client address, requested database, and user name is used to perform
|
||||||
database name of a connection attempt is used to do the
|
authentication. There is no <quote>fall-through</> or
|
||||||
authentication step. There is no <quote>fall-through</> or
|
|
||||||
<quote>backup</>: if one record is chosen and the authentication
|
<quote>backup</>: if one record is chosen and the authentication
|
||||||
fails, the following records are not considered. If no record
|
fails, subsequent records are not considered. If no record matches,
|
||||||
matches, the access will be denied.
|
access is denied.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A record may have one of the three formats
|
A record may have one of the three formats
|
||||||
<synopsis>
|
<synopsis>
|
||||||
local <replaceable>database</replaceable> <replaceable>authentication-method</replaceable> [ <replaceable>authentication-option</replaceable> ]
|
local <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>authentication-method</replaceable> [ <replaceable>authentication-option</replaceable> ]
|
||||||
host <replaceable>database</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable> [ <replaceable>authentication-option</replaceable> ]
|
host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable>
|
||||||
hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable> [ <replaceable>authentication-option</replaceable> ]
|
hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable>
|
||||||
</synopsis>
|
</synopsis>
|
||||||
The meaning of the fields is as follows:
|
The meaning of the fields is as follows:
|
||||||
|
|
||||||
@ -97,7 +95,7 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><literal>local</literal></term>
|
<term><literal>local</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This record pertains to connection attempts over Unix domain
|
This record applies to connection attempts using Unix domain
|
||||||
sockets.
|
sockets.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@ -107,10 +105,11 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><literal>host</literal></term>
|
<term><literal>host</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This record pertains to connection attempts over TCP/IP
|
This record applied to connection attempts using TCP/IP networks.
|
||||||
networks. Note that TCP/IP connections are completely disabled
|
Note that TCP/IP connections are disabled unless the server is
|
||||||
unless the server is started with the <option>-i</option> switch or
|
started with the <option>-i</option> option or the
|
||||||
the equivalent configuration parameter is set.
|
<literal>tcpip_socket</> <filename>postgresql.conf</>
|
||||||
|
configuration parameter is enabled.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -119,13 +118,13 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><literal>hostssl</literal></term>
|
<term><literal>hostssl</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This record pertains to connection attempts with SSL over
|
This record applies to connection attempts using SSL over
|
||||||
TCP/IP. To make use of this option the server must be
|
TCP/IP. To make use of this option the server must be
|
||||||
built with SSL support enabled. Furthermore, SSL must be
|
built with SSL support enabled. Furthermore, SSL must be
|
||||||
enabled with the <option>-l</> option or equivalent configuration
|
enabled with the <option>-l</> option or equivalent configuration
|
||||||
setting when the server is started. (Note: <literal>host</literal>
|
setting when the server is started. (Note: <literal>host</literal>
|
||||||
records will match either SSL or non-SSL connection attempts, but
|
records will match either SSL or non-SSL connection attempts, but
|
||||||
<literal>hostssl</literal> records match only SSL connections.)
|
<literal>hostssl</literal> records requires SSL connections.)
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -134,12 +133,35 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><replaceable>database</replaceable></term>
|
<term><replaceable>database</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Specifies the database that this record applies to. The value
|
Specifies the database for this record. The value
|
||||||
<literal>all</literal> specifies that it applies to all
|
<literal>all</literal> specifies that it applies to all
|
||||||
databases, while the value <literal>sameuser</> identifies the
|
databases, while the value <literal>sameuser</> identifies the
|
||||||
database with the same name as the connecting user. Otherwise,
|
database with the same name as the connecting user. The value
|
||||||
this is the name of a specific <productname>PostgreSQL</productname>
|
<literal>samegroup</> identifies a group with the same name as
|
||||||
database.
|
the database name. Only members of this group can connect to the
|
||||||
|
database. Otherwise, this is the name of a specific
|
||||||
|
<productname>PostgreSQL</productname> database. Multiple database
|
||||||
|
names can be supplied by separating them with commas. A file
|
||||||
|
containing database names can be specified by preceding the file
|
||||||
|
name with <literal>@</>. The file must be in the same directory
|
||||||
|
as <filename>pg_hba.conf</>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable>user</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Specifies the user for this record. The value
|
||||||
|
<literal>all</literal> specifies that it applies to all users.
|
||||||
|
Otherwise, this is the name of a specific
|
||||||
|
<productname>PostgreSQL</productname> user. Multiple user names
|
||||||
|
can be supplied by separating them with commas. Group names can
|
||||||
|
be specified by preceding the group name with <literal>+</>. A
|
||||||
|
file containing user names can be specified by preceding the file
|
||||||
|
name with <literal>@</>. The file must be in the same directory
|
||||||
|
as <filename>pg_hba.conf</>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -149,10 +171,9 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><replaceable>IP mask</replaceable></term>
|
<term><replaceable>IP mask</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
These two fields specify to which client machines a
|
These two fields specify the client machine IP addresses
|
||||||
<literal>host</literal> or <literal>hostssl</literal>
|
(<literal>host</literal> or <literal>hostssl</literal>) for this
|
||||||
record applies, based on their IP
|
record. (Of course IP addresses can be spoofed but this
|
||||||
address. (Of course IP addresses can be spoofed but this
|
|
||||||
consideration is beyond the scope of
|
consideration is beyond the scope of
|
||||||
<productname>PostgreSQL</productname>.) The precise logic is that
|
<productname>PostgreSQL</productname>.) The precise logic is that
|
||||||
<blockquote>
|
<blockquote>
|
||||||
@ -169,10 +190,9 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><replaceable>authentication method</replaceable></term>
|
<term><replaceable>authentication method</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Specifies the method that users must use to authenticate themselves
|
Specifies the authentication method to use when connecting via
|
||||||
when connecting under the control of this authentication record.
|
this record. The possible choices are summarized here; details
|
||||||
The possible choices are summarized here,
|
are in <xref linkend="auth-methods">.
|
||||||
details are in <xref linkend="auth-methods">.
|
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
@ -190,31 +210,8 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><literal>reject</></term>
|
<term><literal>reject</></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The connection is rejected unconditionally. This is mostly
|
The connection is rejected unconditionally. This is useful for
|
||||||
useful to <quote>filter out</> certain hosts from a group.
|
<quote>filtering out</> certain hosts from a group.
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><literal>password</></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The client is required to supply a password which is required to
|
|
||||||
match the database password that was set up for the user.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
An optional file name may be specified after the
|
|
||||||
<literal>password</literal> keyword. This file is expected to
|
|
||||||
contain a list of users who may connect using this record,
|
|
||||||
and optionally alternative passwords for them.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The password is sent over the wire in clear text. For better
|
|
||||||
protection, use the <literal>md5</literal> or
|
|
||||||
<literal>crypt</literal> methods.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -223,17 +220,9 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><literal>md5</></term>
|
<term><literal>md5</></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Like the <literal>password</literal> method, but the password
|
Requires the client to supply an MD5 encrypted password for
|
||||||
is sent over the wire encrypted using a simple
|
authentication. This is the only method that allows encrypted
|
||||||
challenge-response protocol. This protects against incidental
|
passwords to be stored in pg_shadow.
|
||||||
wire-sniffing. This is now the recommended choice for
|
|
||||||
password-based authentication.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The name of a file may follow the
|
|
||||||
<literal>md5</literal> keyword. It contains a list of users
|
|
||||||
who may connect using this record.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -242,14 +231,20 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><literal>crypt</></term>
|
<term><literal>crypt</></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Like the <literal>md5</literal> method but uses older crypt
|
Like <literal>md5</literal> method but uses older crypt
|
||||||
encryption, which is needed for pre-7.2
|
encryption, which is needed for pre-7.2 clients.
|
||||||
clients. <literal>md5</literal> is
|
<literal>md5</literal> is preferred for 7.2 and later clients.
|
||||||
preferred for 7.2 and later clients. The <literal>crypt</>
|
</para>
|
||||||
method is not compatible with encrypting passwords in
|
</listitem>
|
||||||
<filename>pg_shadow</>, and may fail if client and server
|
</varlistentry>
|
||||||
machines have different implementations of the crypt() library
|
|
||||||
routine.
|
<varlistentry>
|
||||||
|
<term><literal>password</></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Same as "md5", but the password is sent in cleartext over the
|
||||||
|
network. This should not be used on untrusted networks.
|
||||||
|
</para>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -278,34 +273,36 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<term><literal>ident</></term>
|
<term><literal>ident</></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The identity of the user as determined on login to the
|
For TCP/IP connections, authentication is done by contacting
|
||||||
operating system is used by <productname>PostgreSQL</productname>
|
the <firstterm>ident</firstterm> server on the client host.
|
||||||
to determine whether the user
|
This is only as secure as the client machine. You must specify
|
||||||
is allowed to connect as the requested database user.
|
the map name after the 'ident' keyword. It determines how to
|
||||||
For TCP/IP connections the user's identity is determined by
|
map remote user names to PostgreSQL user names. If you use
|
||||||
contacting the <firstterm>ident</firstterm> server on the client
|
"sameuser", the user names are assumed to be identical. If
|
||||||
host. (Note that this is only as reliable as the remote ident
|
not, the map name is looked up in the $PGDATA/pg_ident.conf
|
||||||
server; ident authentication should never be used for remote hosts
|
file. The connection is accepted if that file contains an
|
||||||
whose administrators are not trustworthy.)
|
entry for this map name with the ident-supplied user name and
|
||||||
On operating systems
|
the requested PostgreSQL user name.
|
||||||
supporting <symbol>SO_PEERCRED</> requests for Unix domain sockets,
|
</para>
|
||||||
ident authentication is possible for local connections;
|
<para>
|
||||||
the system is then asked for the connecting user's identity.
|
On machines that support unix-domain socket credentials
|
||||||
|
(currently Linux, FreeBSD, NetBSD, and BSD/OS), ident allows
|
||||||
|
reliable authentication of 'local' connections without ident
|
||||||
|
running on the local machine.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
On systems without <symbol>SO_PEERCRED</> requests, ident
|
||||||
|
authentication is only available for TCP/IP connections. As a
|
||||||
|
work around, it is possible to specify the <systemitem
|
||||||
|
class="systemname">localhost</> address <systemitem
|
||||||
|
class="systemname">127.0.0.1</> and make connections to this
|
||||||
|
address.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
On systems without <symbol>SO_PEERCRED</> requests, ident authentication
|
Following the <literal>ident</> keyword, an <firstterm>ident
|
||||||
is only available for TCP/IP connections. As a workaround,
|
map</firstterm> name should be supplied which specifies which
|
||||||
it is possible to
|
operating system users equate with which database users. See
|
||||||
specify the <systemitem class="systemname">localhost</> address
|
below for details.
|
||||||
<systemitem class="systemname">127.0.0.1</> and make connections
|
|
||||||
to this address.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <replaceable>authentication option</replaceable> following
|
|
||||||
the <literal>ident</> keyword specifies the name of an
|
|
||||||
<firstterm>ident map</firstterm> that specifies which operating
|
|
||||||
system users equate with which database users. See below for
|
|
||||||
details.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -315,17 +312,16 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This authentication type operates similarly to
|
This authentication type operates similarly to
|
||||||
<firstterm>password</firstterm>, with the main difference that
|
<firstterm>password</firstterm> except that it uses PAM
|
||||||
it will use PAM (Pluggable Authentication Modules) as the
|
(Pluggable Authentication Modules) as the authentication
|
||||||
authentication mechanism. The <replaceable>authentication
|
mechanism. The default PAM service name is
|
||||||
option</replaceable> following the <literal>pam</> keyword
|
<literal>postgresql</literal>. You can optionally supply you
|
||||||
specifies the service name that will be passed to PAM. The
|
own service name after the <literal>pam</> keyword in the
|
||||||
default service name is <literal>postgresql</literal>.
|
file. For more information about PAM, please read the <ulink
|
||||||
For more information about PAM, please read the <ulink
|
url="http://www.kernel.org/pub/linux/libs/pam/"><productname>L
|
||||||
url="http://www.kernel.org/pub/linux/libs/pam/"><productname>Linux-PAM</productname>
|
inux-PAM</productname> Page</ulink> and the <ulink
|
||||||
Page</ulink> and/or the <ulink
|
url="http://www.sun.com/software/solaris/pam/"><systemitem
|
||||||
url="http://www.sun.com/software/solaris/pam/"><systemitem class="osname">Solaris</> PAM
|
class="osname">Solaris</> PAM Page</ulink>.
|
||||||
Page</ulink>.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -336,42 +332,33 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><replaceable>authentication option</replaceable></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This field is interpreted differently depending on the
|
|
||||||
authentication method, as described above.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Since the <filename>pg_hba.conf</filename> records are examined
|
Since the <filename>pg_hba.conf</filename> records are examined
|
||||||
sequentially for each connection attempt, the order of the records is
|
sequentially for each connection attempt, the order of the records is
|
||||||
very significant. Typically, earlier records will have tight
|
significant. Typically, earlier records will have tight connection
|
||||||
connection match parameters and weaker authentication methods,
|
match parameters and weaker authentication methods, while later
|
||||||
while later records will have looser match parameters and stronger
|
records will have looser match parameters and stronger authentication
|
||||||
authentication methods. For example, one might wish to use
|
methods. For example, one might wish to use <literal>trust</>
|
||||||
<literal>trust</> authentication for local TCP connections but
|
authentication for local TCP connections but require a password for
|
||||||
require a password for remote TCP connections. In this case a
|
remote TCP connections. In this case a record specifying
|
||||||
record specifying <literal>trust</> authentication for connections
|
<literal>trust</> authentication for connections from 127.0.0.1 would
|
||||||
from 127.0.0.1 would appear before a record specifying password
|
appear before a record specifying password authentication for a wider
|
||||||
authentication for a wider range of allowed client IP addresses.
|
range of allowed client IP addresses.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>SIGHUP</primary>
|
<primary>SIGHUP</primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
The <filename>pg_hba.conf</filename> file is read on start-up
|
The <filename>pg_hba.conf</filename> file is read on start-up and when
|
||||||
and when the <application>postmaster</> receives a
|
the <application>postmaster</> receives a
|
||||||
<systemitem>SIGHUP</systemitem> signal. If you edit the file on an
|
<systemitem>SIGHUP</systemitem> signal. If you edit the file on an
|
||||||
active system, you will need to signal the <application>postmaster</>
|
active system, you will need to signal the <application>postmaster</>
|
||||||
(using <literal>pg_ctl reload</> or <literal>kill -HUP</>)
|
(using <literal>pg_ctl reload</> or <literal>kill -HUP</>) to make it
|
||||||
to make it re-read the file.
|
re-read the file.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -382,27 +369,27 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
|
|||||||
<example id="example-pg-hba.conf">
|
<example id="example-pg-hba.conf">
|
||||||
<title>An example <filename>pg_hba.conf</filename> file</title>
|
<title>An example <filename>pg_hba.conf</filename> file</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
# TYPE DATABASE IP_ADDRESS MASK AUTHTYPE MAP
|
# TYPE DATABASE USER IP_ADDRESS MASK AUTHTYPE
|
||||||
|
|
||||||
# Allow any user on the local system to connect to any
|
# Allow any user on the local system to connect to any
|
||||||
# database under any username, but only via an IP connection:
|
# database under any user name, but only via an IP connection:
|
||||||
|
|
||||||
host all 127.0.0.1 255.255.255.255 trust
|
host all all 127.0.0.1 255.255.255.255 trust
|
||||||
|
|
||||||
# The same, over Unix-socket connections:
|
# The same, over Unix-socket connections:
|
||||||
|
|
||||||
local all trust
|
local all all trust
|
||||||
|
|
||||||
# Allow any user from any host with IP address 192.168.93.x to
|
# Allow any user from any host with IP address 192.168.93.x to
|
||||||
# connect to database "template1" as the same username that ident on that
|
# connect to database "template1" as the same user name that ident on that
|
||||||
# host identifies him as (typically his Unix username):
|
# host identifies him as (typically his Unix user name):
|
||||||
|
|
||||||
host template1 192.168.93.0 255.255.255.0 ident sameuser
|
host template1 all 192.168.93.0 255.255.255.0 ident sameuser
|
||||||
|
|
||||||
# Allow a user from host 192.168.12.10 to connect to database "template1"
|
# Allow a user from host 192.168.12.10 to connect to database "template1"
|
||||||
# if the user's password in pg_shadow is correctly supplied:
|
# if the user's password is correctly supplied:
|
||||||
|
|
||||||
host template1 192.168.12.10 255.255.255.255 md5
|
host template1 all 192.168.12.10 255.255.255.255 md5
|
||||||
|
|
||||||
# In the absence of preceding "host" lines, these two lines will reject
|
# In the absence of preceding "host" lines, these two lines will reject
|
||||||
# all connection attempts from 192.168.54.1 (since that entry will be
|
# all connection attempts from 192.168.54.1 (since that entry will be
|
||||||
@ -410,8 +397,8 @@ host template1 192.168.12.10 255.255.255.255 md5
|
|||||||
# else on the Internet. The zero mask means that no bits of the host IP
|
# else on the Internet. The zero mask means that no bits of the host IP
|
||||||
# address are considered, so it matches any host:
|
# address are considered, so it matches any host:
|
||||||
|
|
||||||
host all 192.168.54.1 255.255.255.255 reject
|
host all all 192.168.54.1 255.255.255.255 reject
|
||||||
host all 0.0.0.0 0.0.0.0 krb5
|
host all all 0.0.0.0 0.0.0.0 krb5
|
||||||
|
|
||||||
# Allow users from 192.168.x.x hosts to connect to any database, if they
|
# Allow users from 192.168.x.x hosts to connect to any database, if they
|
||||||
# pass the ident check. If, for example, ident says the user is "bryanh"
|
# pass the ident check. If, for example, ident says the user is "bryanh"
|
||||||
@ -419,7 +406,7 @@ host all 0.0.0.0 0.0.0.0 krb5
|
|||||||
# is allowed if there is an entry in pg_ident.conf for map "omicron" that
|
# is allowed if there is an entry in pg_ident.conf for map "omicron" that
|
||||||
# says "bryanh" is allowed to connect as "guest1":
|
# says "bryanh" is allowed to connect as "guest1":
|
||||||
|
|
||||||
host all 192.168.0.0 255.255.0.0 ident omicron
|
host all all 192.168.0.0 255.255.0.0 ident omicron
|
||||||
|
|
||||||
# If these are the only two lines for local connections, they will allow
|
# If these are the only two lines for local connections, they will allow
|
||||||
# local users to connect only to their own databases (database named the
|
# local users to connect only to their own databases (database named the
|
||||||
@ -429,8 +416,8 @@ host all 192.168.0.0 255.255.0.0 ident omicron
|
|||||||
# cases. (If you prefer to use ident authorization, an ident map can
|
# cases. (If you prefer to use ident authorization, an ident map can
|
||||||
# serve a parallel purpose to the password list file used here.)
|
# serve a parallel purpose to the password list file used here.)
|
||||||
|
|
||||||
local sameuser md5
|
local sameuser all md5
|
||||||
local all md5 admins
|
local all @admins md5
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</example>
|
</example>
|
||||||
</para>
|
</para>
|
||||||
@ -490,86 +477,49 @@ local all md5 admins
|
|||||||
<title>Password authentication</title>
|
<title>Password authentication</title>
|
||||||
|
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>password</primary>
|
<primary>MD5</>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>MD5</>
|
<primary>crypt</>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>password</primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Password-based authentication methods include <literal>md5</>,
|
Password-based authentication methods include <literal>md5</>,
|
||||||
<literal>crypt</>, and <literal>password</>. These methods operate
|
<literal>crypt</>, and <literal>password</>. These methods operate
|
||||||
similarly except for the way that the password is sent across the
|
similarly except for the way that the password is sent across the
|
||||||
connection. If you are at all concerned about password <quote>sniffing</>
|
connection. If you are at all concerned about password
|
||||||
attacks then <literal>md5</> is preferred, with <literal>crypt</> a
|
<quote>sniffing</> attacks then <literal>md5</> is preferred, with
|
||||||
second choice if you must support obsolete clients. Plain
|
<literal>crypt</> a second choice if you must support pre-7.2
|
||||||
<literal>password</> should especially be avoided for connections over
|
clients. Plain <literal>password</> should especially be avoided for
|
||||||
the open Internet (unless you use SSL, SSH, or other communications
|
connections over the open Internet (unless you use SSL, SSH, or
|
||||||
security wrappers around the connection).
|
other communications security wrappers around the connection).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<productname>PostgreSQL</productname> database passwords are separate from
|
<productname>PostgreSQL</productname> database passwords are
|
||||||
operating system user passwords. Ordinarily, the password for each
|
separate from operating system user passwords. Ordinarily, the
|
||||||
database user is stored in the pg_shadow system catalog table.
|
password for each database user is stored in the pg_shadow system
|
||||||
Passwords can be managed with the query language commands
|
catalog table. Passwords can be managed with the query language
|
||||||
<command>CREATE USER</command> and <command>ALTER USER</command>,
|
commands <command>CREATE USER</command> and <command>ALTER
|
||||||
e.g., <userinput>CREATE USER foo WITH PASSWORD
|
USER</command>, e.g., <userinput>CREATE USER foo WITH PASSWORD
|
||||||
'secret';</userinput>. By default, that is, if no password has
|
'secret';</userinput>. By default, that is, if no password has been
|
||||||
been set up, the stored password is <literal>NULL</literal>
|
set up, the stored password is <literal>NULL</literal> and password
|
||||||
and password authentication will always fail for that user.
|
authentication will always fail for that user.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To restrict the set of users that are allowed to connect to certain
|
To restrict the set of users that are allowed to connect to certain
|
||||||
databases, list the set of users in a separate file (one user name
|
databases, list the users separated by commas, or in a separate
|
||||||
per line) in the same directory that <filename>pg_hba.conf</> is in,
|
file. The file should contain user names separated by commas or one
|
||||||
and mention the (base) name of the file after the
|
user name per line, and be in the same directory as
|
||||||
<literal>password</>, <literal>md5</>, or <literal>crypt</> keyword,
|
<filename>pg_hba.conf</>. Mention the (base) name of the file
|
||||||
respectively, in <filename>pg_hba.conf</>. If you do not use this
|
preceded with <literal>@</>in the <literal>USER</> column. The
|
||||||
feature, then any user that is known to the database system can
|
<literal>DATABASE</> column can similarly accept a list of values or
|
||||||
connect to any database (so long as he supplies the correct password,
|
a file name. You can also specify group names by preceding the group
|
||||||
of course).
|
name with <literal>+</>.
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
These files can also be used to apply a different set of passwords
|
|
||||||
to a particular database or set thereof. In that case, the files
|
|
||||||
have a format similar to the standard Unix password file
|
|
||||||
<filename>/etc/passwd</filename>, that is,
|
|
||||||
<synopsis>
|
|
||||||
<replaceable>username</replaceable>:<replaceable>password</replaceable>
|
|
||||||
</synopsis>
|
|
||||||
Any extra colon-separated fields following the password are
|
|
||||||
ignored. The password is expected to be encrypted using the
|
|
||||||
system's <function>crypt()</function> function. The utility
|
|
||||||
program <application>pg_passwd</application> that is installed
|
|
||||||
with <productname>PostgreSQL</productname> can be used to manage
|
|
||||||
these password files.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Lines with and without passwords can be mixed in secondary
|
|
||||||
password files. Lines without password indicate use of the main
|
|
||||||
password in <literal>pg_shadow</> that is managed by
|
|
||||||
<command>CREATE USER</> and <command>ALTER USER</>. Lines with
|
|
||||||
passwords will cause that password to be used. A password entry of
|
|
||||||
<quote>+</quote> also means using the pg_shadow password.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Alternative passwords cannot be used when using the <literal>md5</>
|
|
||||||
or <literal>crypt</> methods. The file will be read as
|
|
||||||
usual, but the password field will simply be ignored and the
|
|
||||||
<literal>pg_shadow</> password will always be used.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Note that using alternative passwords like this means that one can
|
|
||||||
no longer use <command>ALTER USER</command> to change one's
|
|
||||||
password. It will appear to work but the password one is
|
|
||||||
changing is not the password that the system will end up
|
|
||||||
using.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
@ -588,10 +538,10 @@ local all md5 admins
|
|||||||
<productname>Kerberos</productname> system is far beyond the scope
|
<productname>Kerberos</productname> system is far beyond the scope
|
||||||
of this document; in all generality it can be quite complex (yet
|
of this document; in all generality it can be quite complex (yet
|
||||||
powerful). The <ulink
|
powerful). The <ulink
|
||||||
url="http://www.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html">Kerberos
|
url="http://www.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html">Kerb
|
||||||
<acronym>FAQ</></ulink> or <ulink
|
eros <acronym>FAQ</></ulink> or <ulink
|
||||||
url="ftp://athena-dist.mit.edu">MIT Project Athena</ulink> can be
|
url="ftp://athena-dist.mit.edu">MIT Project Athena</ulink> can be a
|
||||||
a good starting point for exploration. Several sources for
|
good starting point for exploration. Several sources for
|
||||||
<productname>Kerberos</> distributions exist.
|
<productname>Kerberos</> distributions exist.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@ -606,34 +556,33 @@ local all md5 admins
|
|||||||
<para>
|
<para>
|
||||||
<productname>PostgreSQL</> operates like a normal Kerberos service.
|
<productname>PostgreSQL</> operates like a normal Kerberos service.
|
||||||
The name of the service principal is
|
The name of the service principal is
|
||||||
<replaceable>servicename/hostname@realm</>, where
|
<replaceable>servicename/hostname@realm</>, where
|
||||||
<replaceable>servicename</> is <literal>postgres</literal>
|
<replaceable>servicename</> is <literal>postgres</literal> (unless a
|
||||||
(unless a different service name was selected at configure time
|
different service name was selected at configure time with
|
||||||
with <literal>./configure --with-krb-srvnam=whatever</>).
|
<literal>./configure --with-krb-srvnam=whatever</>).
|
||||||
<replaceable>hostname</> is the fully qualified domain name of the server
|
<replaceable>hostname</> is the fully qualified domain name of the
|
||||||
machine. The service principal's realm is the preferred realm of the
|
server machine. The service principal's realm is the preferred realm
|
||||||
server machine.
|
of the server machine.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Client principals must have their <productname>PostgreSQL</> user name as
|
Client principals must have their <productname>PostgreSQL</> user
|
||||||
their first component, for example
|
name as their first component, for example
|
||||||
<replaceable>pgusername/otherstuff@realm</>.
|
<replaceable>pgusername/otherstuff@realm</>. At present the realm of
|
||||||
At present the realm of the client is not checked by
|
the client is not checked by <productname>PostgreSQL</>; so if you
|
||||||
<productname>PostgreSQL</>; so
|
have cross-realm authentication enabled, then any principal in any
|
||||||
if you have cross-realm authentication enabled, then any principal
|
realm that can communicate with yours will be accepted.
|
||||||
in any realm that can communicate with yours will be accepted.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Make sure that your server key file is readable (and
|
Make sure that your server key file is readable (and preferably only
|
||||||
preferably only readable) by the
|
readable) by the <productname>PostgreSQL</productname> server
|
||||||
<productname>PostgreSQL</productname> server account (see
|
account (see <xref linkend="postgres-user">). The location of the
|
||||||
<xref linkend="postgres-user">). The location of the key file
|
key file is specified with the <varname>krb_server_keyfile</> run
|
||||||
is specified with the <varname>krb_server_keyfile</> run time
|
time configuration parameter. (See also <xref
|
||||||
configuration parameter. (See also <xref linkend="runtime-config">.)
|
linkend="runtime-config">.) The default is <filename>/etc/srvtab</>
|
||||||
The default is <filename>/etc/srvtab</> if you are using Kerberos 4
|
if you are using Kerberos 4 and
|
||||||
and <filename>FILE:/usr/local/pgsql/etc/krb5.keytab</> (or whichever
|
<filename>FILE:/usr/local/pgsql/etc/krb5.keytab</> (or whichever
|
||||||
directory was specified as <varname>sysconfdir</> at build time)
|
directory was specified as <varname>sysconfdir</> at build time)
|
||||||
with Kerberos 5.
|
with Kerberos 5.
|
||||||
</para>
|
</para>
|
||||||
@ -649,18 +598,20 @@ local all md5 admins
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
When connecting to the database make sure you have a ticket for a
|
When connecting to the database make sure you have a ticket for a
|
||||||
principal matching the requested database user name.
|
principal matching the requested database user name. An example: For
|
||||||
An example: For database user name <literal>fred</>, both principal
|
database user name <literal>fred</>, both principal
|
||||||
<literal>fred@EXAMPLE.COM</> and
|
<literal>fred@EXAMPLE.COM</> and
|
||||||
<literal>fred/users.example.com@EXAMPLE.COM</> can be
|
<literal>fred/users.example.com@EXAMPLE.COM</> can be used to
|
||||||
used to authenticate to the database server.
|
authenticate to the database server.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If you use <application>mod_auth_krb</application> and <application>mod_perl</application> on your <productname>Apache</productname> web server,
|
If you use <application>mod_auth_krb</application> and
|
||||||
you can use <literal>AuthType KerberosV5SaveCredentials</literal> with a <application>mod_perl</application>
|
<application>mod_perl</application> on your
|
||||||
script. This gives secure database access over the web, no extra
|
<productname>Apache</productname> web server, you can use
|
||||||
passwords required.
|
<literal>AuthType KerberosV5SaveCredentials</literal> with a
|
||||||
|
<application>mod_perl</application> script. This gives secure
|
||||||
|
database access over the web, no extra passwords required.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
@ -707,55 +658,54 @@ local all md5 admins
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
On systems supporting <symbol>SO_PEERCRED</symbol> requests for Unix-domain sockets,
|
On systems supporting <symbol>SO_PEERCRED</symbol> requests for
|
||||||
ident authentication can also be applied to local connections. In this
|
Unix-domain sockets, ident authentication can also be applied to
|
||||||
case, no security risk is added by using ident authentication; indeed
|
local connections. In this case, no security risk is added by using
|
||||||
it is a preferable choice for local connections on such a system.
|
ident authentication; indeed it is a preferable choice for local
|
||||||
|
connections on such systems.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When using ident-based authentication, after having determined the
|
When using ident-based authentication, after having determined the
|
||||||
name of the operating system user that initiated the connection,
|
name of the operating system user that initiated the connection,
|
||||||
<productname>PostgreSQL</productname> checks whether that user is allowed
|
<productname>PostgreSQL</productname> checks whether that user is
|
||||||
to connect as the database user he is requesting to connect as.
|
allowed to connect as the database user he is requesting to connect
|
||||||
This is controlled by the ident map
|
as. This is controlled by the ident map argument that follows the
|
||||||
argument that follows the <literal>ident</> keyword in the
|
<literal>ident</> keyword in the <filename>pg_hba.conf</filename>
|
||||||
<filename>pg_hba.conf</filename> file. There is a predefined ident map
|
file. There is a predefined ident map <literal>sameuser</literal>,
|
||||||
<literal>sameuser</literal>, which allows any operating system
|
which allows any operating system user to connect as the database
|
||||||
user to connect as the database user of the same name (if the
|
user of the same name (if the latter exists). Other maps must be
|
||||||
latter exists). Other maps must be created manually.
|
created manually.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<indexterm><primary>pg_ident.conf</primary></indexterm>
|
<indexterm><primary>pg_ident.conf</primary></indexterm> Ident maps
|
||||||
Ident maps other than <literal>sameuser</literal> are defined
|
other than <literal>sameuser</literal> are defined in the file
|
||||||
in the file <filename>pg_ident.conf</filename>
|
<filename>pg_ident.conf</filename> in the data directory, which
|
||||||
in the data directory, which contains lines of the general form:
|
contains lines of the general form:
|
||||||
<synopsis>
|
<synopsis>
|
||||||
<replaceable>map-name</> <replaceable>ident-username</> <replaceable>database-username</>
|
<replaceable>map-name</> <replaceable>ident-username</> <replaceable>database-username</>
|
||||||
</synopsis>
|
</synopsis>
|
||||||
Comments and whitespace are handled in the usual way.
|
Comments and whitespace are handled in the usual way. The
|
||||||
The <replaceable>map-name</> is an arbitrary name that will be
|
<replaceable>map-name</> is an arbitrary name that will be used to
|
||||||
used to refer to this mapping in <filename>pg_hba.conf</filename>.
|
refer to this mapping in <filename>pg_hba.conf</filename>. The other
|
||||||
The other two fields specify which operating system user is
|
two fields specify which operating system user is allowed to connect
|
||||||
allowed to connect as which database user. The same
|
as which database user. The same <replaceable>map-name</> can be
|
||||||
<replaceable>map-name</> can be used repeatedly to specify more
|
used repeatedly to specify more user-mappings within a single map.
|
||||||
user-mappings within a single map. There is no restriction regarding
|
There is no restriction regarding how many database users a given
|
||||||
how many
|
operating system user may correspond to and vice versa.
|
||||||
database users a given operating system user may correspond to and vice
|
|
||||||
versa.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>SIGHUP</primary>
|
<primary>SIGHUP</primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
The <filename>pg_ident.conf</filename> file is read on start-up
|
The <filename>pg_ident.conf</filename> file is read on start-up and
|
||||||
and when the <application>postmaster</> receives a
|
when the <application>postmaster</> receives a
|
||||||
<systemitem>SIGHUP</systemitem> signal. If you edit the file on an
|
<systemitem>SIGHUP</systemitem> signal. If you edit the file on an
|
||||||
active system, you will need to signal the <application>postmaster</>
|
active system, you will need to signal the <application>postmaster</>
|
||||||
(using <literal>pg_ctl reload</> or <literal>kill -HUP</>)
|
(using <literal>pg_ctl reload</> or <literal>kill -HUP</>) to make it
|
||||||
to make it re-read the file.
|
re-read the file.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -763,13 +713,14 @@ local all md5 admins
|
|||||||
conjunction with the <filename>pg_hba.conf</> file in <xref
|
conjunction with the <filename>pg_hba.conf</> file in <xref
|
||||||
linkend="example-pg-hba.conf"> is shown in <xref
|
linkend="example-pg-hba.conf"> is shown in <xref
|
||||||
linkend="example-pg-ident.conf">. In this example setup, anyone
|
linkend="example-pg-ident.conf">. In this example setup, anyone
|
||||||
logged in to a machine on the 192.168 network that does not have
|
logged in to a machine on the 192.168 network that does not have the
|
||||||
the Unix user name <systemitem>bryanh</>, <systemitem>ann</>, or <systemitem>robert</> would not be granted access.
|
Unix user name <systemitem>bryanh</>, <systemitem>ann</>, or
|
||||||
Unix user <systemitem>robert</> would only be allowed access when he tries to
|
<systemitem>robert</> would not be granted access. Unix user
|
||||||
connect as <productname>PostgreSQL</> user <systemitem>bob</>,
|
<systemitem>robert</> would only be allowed access when he tries to
|
||||||
not as <systemitem>robert</>
|
connect as <productname>PostgreSQL</> user <systemitem>bob</>, not
|
||||||
or anyone else. <systemitem>ann</> would only be allowed to connect as
|
as <systemitem>robert</> or anyone else. <systemitem>ann</> would
|
||||||
<systemitem>ann</>. User <systemitem>bryanh</> would be allowed to connect as either
|
only be allowed to connect as <systemitem>ann</>. User
|
||||||
|
<systemitem>bryanh</> would be allowed to connect as either
|
||||||
<systemitem>bryanh</> himself or as <systemitem>guest1</>.
|
<systemitem>bryanh</> himself or as <systemitem>guest1</>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@ -780,7 +731,7 @@ local all md5 admins
|
|||||||
|
|
||||||
omicron bryanh bryanh
|
omicron bryanh bryanh
|
||||||
omicron ann ann
|
omicron ann ann
|
||||||
# bob has username robert on these machines
|
# bob has user name robert on these machines
|
||||||
omicron robert bob
|
omicron robert bob
|
||||||
# bryanh can also connect as guest1
|
# bryanh can also connect as guest1
|
||||||
omicron bryanh guest1
|
omicron bryanh guest1
|
||||||
@ -799,30 +750,30 @@ omicron bryanh guest1
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
No pg_hba.conf entry for host 123.123.123.123, user joeblow, database testdb
|
No pg_hba.conf entry for host 123.123.123.123, user andym, database testdb
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
This is what you are most likely to get if you succeed in
|
This is what you are most likely to get if you succeed in contacting
|
||||||
contacting the server, but it does not want to talk to you. As the
|
the server, but it does not want to talk to you. As the message
|
||||||
message suggests, the server refused the connection request
|
suggests, the server refused the connection request because it found
|
||||||
because it found no authorizing entry in its <filename>pg_hba.conf</filename>
|
no authorizing entry in its <filename>pg_hba.conf</filename>
|
||||||
configuration file.
|
configuration file.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
Password authentication failed for user 'joeblow'
|
Password authentication failed for user 'andym'
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
Messages like this indicate that you contacted the server, and
|
Messages like this indicate that you contacted the server, and it is
|
||||||
it is willing to talk to you, but not until you pass the
|
willing to talk to you, but not until you pass the authorization
|
||||||
authorization method specified in the
|
method specified in the <filename>pg_hba.conf</filename> file. Check
|
||||||
<filename>pg_hba.conf</filename> file. Check the password you are
|
the password you are providing, or check your Kerberos or ident
|
||||||
providing, or check your Kerberos or ident software if the
|
software if the complaint mentions one of those authentication
|
||||||
complaint mentions one of those authentication types.
|
types.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
FATAL 1: user "joeblow" does not exist
|
FATAL 1: user "andym" does not exist
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
The indicated user name was not found.
|
The indicated user name was not found.
|
||||||
</para>
|
</para>
|
||||||
@ -837,9 +788,9 @@ FATAL 1: Database "testdb" does not exist in the system catalog.
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Note that the server log may contain more information
|
Note that the server log may contain more information about an
|
||||||
about an authentication failure than is reported to the client.
|
authentication failure than is reported to the client. If you are
|
||||||
If you are confused about the reason for a failure, check the log.
|
confused about the reason for a failure, check the log.
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.36 2002/03/19 02:18:12 momjian Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.37 2002/04/04 04:25:45 momjian Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
Complete list of usable sgml source files in this directory.
|
Complete list of usable sgml source files in this directory.
|
||||||
-->
|
-->
|
||||||
@ -125,7 +125,6 @@ Complete list of usable sgml source files in this directory.
|
|||||||
<!entity pgCtl system "pg_ctl-ref.sgml">
|
<!entity pgCtl system "pg_ctl-ref.sgml">
|
||||||
<!entity pgDump system "pg_dump.sgml">
|
<!entity pgDump system "pg_dump.sgml">
|
||||||
<!entity pgDumpall system "pg_dumpall.sgml">
|
<!entity pgDumpall system "pg_dumpall.sgml">
|
||||||
<!entity pgPasswd system "pg_passwd.sgml">
|
|
||||||
<!entity pgRestore system "pg_restore.sgml">
|
<!entity pgRestore system "pg_restore.sgml">
|
||||||
<!entity pgTclSh system "pgtclsh.sgml">
|
<!entity pgTclSh system "pgtclsh.sgml">
|
||||||
<!entity pgTkSh system "pgtksh.sgml">
|
<!entity pgTkSh system "pgtksh.sgml">
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
<!--
|
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/Attic/pg_passwd.sgml,v 1.10 2001/12/08 03:24:38 thomas Exp $
|
|
||||||
PostgreSQL documentation
|
|
||||||
-->
|
|
||||||
|
|
||||||
<refentry id="APP-PG-PASSWD">
|
|
||||||
<docinfo>
|
|
||||||
<date>2000-11-18</date>
|
|
||||||
</docinfo>
|
|
||||||
|
|
||||||
<refmeta>
|
|
||||||
<refentrytitle id="APP-PG-PASSWD-TITLE"><application>pg_passwd</application></refentrytitle>
|
|
||||||
<manvolnum>1</manvolnum>
|
|
||||||
<refmiscinfo>Application</refmiscinfo>
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname>pg_passwd</refname>
|
|
||||||
<refpurpose>change a secondary <productname>PostgreSQL</> password file</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
|
|
||||||
<refsynopsisdiv>
|
|
||||||
<cmdsynopsis>
|
|
||||||
<command>pg_passwd</command>
|
|
||||||
<arg choice="plain"><replaceable>filename</replaceable></arg>
|
|
||||||
</cmdsynopsis>
|
|
||||||
</refsynopsisdiv>
|
|
||||||
|
|
||||||
<refsect1 id="app-pg-passwd-description">
|
|
||||||
<title>Description</title>
|
|
||||||
<para>
|
|
||||||
<application>pg_passwd</application> is a tool for manipulating flat
|
|
||||||
text password files. These files can control client authentication of
|
|
||||||
the <productname>PostgreSQL</productname> server. More information
|
|
||||||
about setting up this authentication mechanism can be found in the
|
|
||||||
<citetitle>Administrator's Guide</citetitle>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The format of a text password file is one entry per line; the fields
|
|
||||||
of each entry are separated by colons. The first field is the user
|
|
||||||
name, the second field is the encrypted password. Other fields are
|
|
||||||
ignored (to allow password files to be shared between applications
|
|
||||||
that use similar formats). <application>pg_passwd</application>
|
|
||||||
enables users to interactively add entries to such a file, to alter
|
|
||||||
passwords of existing entries, and to encrypt such passwords.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Supply the name of the password file as argument to the
|
|
||||||
<application>pg_passwd</application> command. To be used by
|
|
||||||
PostgreSQL, the file needs to be located in the server's data
|
|
||||||
directory, and the base name of the file needs to be specified in the
|
|
||||||
<filename>pg_hba.conf</filename> access control file.
|
|
||||||
|
|
||||||
<screen>
|
|
||||||
<prompt>$</prompt> <userinput>pg_passwd /usr/local/pgsql/data/passwords</userinput>
|
|
||||||
<computeroutput>File "/usr/local/pgsql/data/passwords" does not exist. Create? (y/n):</computeroutput> <userinput>y</userinput>
|
|
||||||
<prompt>Username:</prompt> <userinput>guest</userinput>
|
|
||||||
<prompt>Password:</prompt>
|
|
||||||
<prompt>Re-enter password:</prompt>
|
|
||||||
</screen>
|
|
||||||
|
|
||||||
where the <literal>Password:</literal> and <literal>Re-enter
|
|
||||||
password:</literal> prompts require the same password input which
|
|
||||||
is not displayed on the terminal. Note that the password is limited
|
|
||||||
to eight useful characters by restrictions of the standard crypt(3)
|
|
||||||
library routine.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The original password file is renamed to
|
|
||||||
<filename>passwords.bk</filename>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To make use of this password file, put a line like the following in
|
|
||||||
<filename>pg_hba.conf</filename>:
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
host mydb 133.65.96.250 255.255.255.255 password passwords
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
which would allow access to database mydb from host 133.65.96.250 using
|
|
||||||
the passwords listed in the <filename>passwords</filename> file (and
|
|
||||||
only to the users listed in that file).
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
It is also useful to have entries in a password file with empty
|
|
||||||
password fields. (This is different from an empty password.) Such
|
|
||||||
entries allow you to restrict users who can access the system. These
|
|
||||||
entries cannot be managed by <application>pg_passwd</application>,
|
|
||||||
but you can edit password files manually.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1 id="app-pg-passwd-seealso">
|
|
||||||
<title>See also</title>
|
|
||||||
<para>
|
|
||||||
<citetitle>PostgreSQL Administrator's Guide</citetitle>
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
||||||
|
|
||||||
<!-- Keep this comment at the end of the file
|
|
||||||
Local variables:
|
|
||||||
mode: sgml
|
|
||||||
sgml-omittag:nil
|
|
||||||
sgml-shorttag:t
|
|
||||||
sgml-minimize-attributes:nil
|
|
||||||
sgml-always-quote-attributes:t
|
|
||||||
sgml-indent-step:1
|
|
||||||
sgml-indent-data:t
|
|
||||||
sgml-parent-document:nil
|
|
||||||
sgml-default-dtd-file:"../reference.ced"
|
|
||||||
sgml-exposed-tags:nil
|
|
||||||
sgml-local-catalogs:"/usr/lib/sgml/catalog"
|
|
||||||
sgml-local-ecat-files:nil
|
|
||||||
End:
|
|
||||||
-->
|
|
@ -1,5 +1,5 @@
|
|||||||
<!-- reference.sgml
|
<!-- reference.sgml
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.24 2002/03/19 02:18:11 momjian Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.25 2002/04/04 04:25:44 momjian Exp $
|
||||||
|
|
||||||
PostgreSQL Reference Manual
|
PostgreSQL Reference Manual
|
||||||
-->
|
-->
|
||||||
@ -191,7 +191,6 @@ Disable this chapter until we have more functions documented.
|
|||||||
&initlocation;
|
&initlocation;
|
||||||
&ipcclean;
|
&ipcclean;
|
||||||
&pgCtl;
|
&pgCtl;
|
||||||
&pgPasswd;
|
|
||||||
&postgres;
|
&postgres;
|
||||||
&postmaster;
|
&postmaster;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.94 2002/03/26 19:15:48 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.95 2002/04/04 04:25:45 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -15,6 +15,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
@ -27,6 +28,7 @@
|
|||||||
#include "libpq/crypt.h"
|
#include "libpq/crypt.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "storage/pmsignal.h"
|
#include "storage/pmsignal.h"
|
||||||
|
#include "utils/acl.h"
|
||||||
#include "utils/array.h"
|
#include "utils/array.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
@ -39,22 +41,75 @@ extern bool Password_encryption;
|
|||||||
|
|
||||||
static void CheckPgUserAclNotNull(void);
|
static void CheckPgUserAclNotNull(void);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------
|
|
||||||
* write_password_file / update_pg_pwd
|
|
||||||
|
/*
|
||||||
|
* fputs_quote
|
||||||
*
|
*
|
||||||
* copy the modified contents of pg_shadow to a file used by the postmaster
|
* Outputs string in quotes, with double-quotes duplicated.
|
||||||
* for user authentication. The file is stored as $PGDATA/global/pg_pwd.
|
* We could use quote_ident(), but that expects varlena.
|
||||||
|
*/
|
||||||
|
static void fputs_quote(char *str, FILE *fp)
|
||||||
|
{
|
||||||
|
fputc('"', fp);
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
fputc(*str, fp);
|
||||||
|
if (*str == '"')
|
||||||
|
fputc('"', fp);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
fputc('"', fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* group_getfilename --- get full pathname of group file
|
||||||
*
|
*
|
||||||
* This function set is both a trigger function for direct updates to pg_shadow
|
* Note that result string is palloc'd, and should be freed by the caller.
|
||||||
* as well as being called directly from create/alter/drop user.
|
*/
|
||||||
*
|
char *
|
||||||
* We raise an error to force transaction rollback if we detect an illegal
|
group_getfilename(void)
|
||||||
* username or password --- illegal being defined as values that would
|
{
|
||||||
* mess up the pg_pwd parser.
|
int bufsize;
|
||||||
*---------------------------------------------------------------------
|
char *pfnam;
|
||||||
|
|
||||||
|
bufsize = strlen(DataDir) + strlen("/global/") +
|
||||||
|
strlen(USER_GROUP_FILE) + 1;
|
||||||
|
pfnam = (char *) palloc(bufsize);
|
||||||
|
snprintf(pfnam, bufsize, "%s/global/%s", DataDir, USER_GROUP_FILE);
|
||||||
|
|
||||||
|
return pfnam;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get full pathname of password file.
|
||||||
|
* Note that result string is palloc'd, and should be freed by the caller.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
user_getfilename(void)
|
||||||
|
{
|
||||||
|
int bufsize;
|
||||||
|
char *pfnam;
|
||||||
|
|
||||||
|
bufsize = strlen(DataDir) + strlen("/global/") +
|
||||||
|
strlen(PWD_FILE) + 1;
|
||||||
|
pfnam = (char *) palloc(bufsize);
|
||||||
|
snprintf(pfnam, bufsize, "%s/global/%s", DataDir, PWD_FILE);
|
||||||
|
|
||||||
|
return pfnam;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write_group_file for trigger update_pg_pwd_and_pg_group
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
write_password_file(Relation rel)
|
write_group_file(Relation urel, Relation grel)
|
||||||
{
|
{
|
||||||
char *filename,
|
char *filename,
|
||||||
*tempname;
|
*tempname;
|
||||||
@ -63,14 +118,14 @@ write_password_file(Relation rel)
|
|||||||
mode_t oumask;
|
mode_t oumask;
|
||||||
HeapScanDesc scan;
|
HeapScanDesc scan;
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
TupleDesc dsc = RelationGetDescr(rel);
|
TupleDesc dsc = RelationGetDescr(grel);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a temporary filename to be renamed later. This prevents the
|
* Create a temporary filename to be renamed later. This prevents the
|
||||||
* backend from clobbering the pg_pwd file while the postmaster might
|
* backend from clobbering the pg_group file while the postmaster might
|
||||||
* be reading from it.
|
* be reading from it.
|
||||||
*/
|
*/
|
||||||
filename = crypt_getpwdfilename();
|
filename = group_getfilename();
|
||||||
bufsize = strlen(filename) + 12;
|
bufsize = strlen(filename) + 12;
|
||||||
tempname = (char *) palloc(bufsize);
|
tempname = (char *) palloc(bufsize);
|
||||||
|
|
||||||
@ -79,88 +134,89 @@ write_password_file(Relation rel)
|
|||||||
fp = AllocateFile(tempname, "w");
|
fp = AllocateFile(tempname, "w");
|
||||||
umask(oumask);
|
umask(oumask);
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
elog(ERROR, "write_password_file: unable to write %s: %m", tempname);
|
elog(ERROR, "write_group_file: unable to write %s: %m", tempname);
|
||||||
|
|
||||||
/* read table */
|
/* read table */
|
||||||
scan = heap_beginscan(rel, false, SnapshotSelf, 0, NULL);
|
scan = heap_beginscan(grel, false, SnapshotSelf, 0, NULL);
|
||||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||||
{
|
{
|
||||||
Datum datum_n,
|
Datum datum, grolist_datum;
|
||||||
datum_p,
|
bool isnull;
|
||||||
datum_v;
|
char *groname;
|
||||||
bool null_n,
|
IdList *grolist_p;
|
||||||
null_p,
|
AclId *aidp;
|
||||||
null_v;
|
int i, j,
|
||||||
char *str_n,
|
num;
|
||||||
*str_p,
|
char *usename;
|
||||||
*str_v;
|
bool first_user = true;
|
||||||
int i;
|
|
||||||
|
|
||||||
datum_n = heap_getattr(tuple, Anum_pg_shadow_usename, dsc, &null_n);
|
datum = heap_getattr(tuple, Anum_pg_group_groname, dsc, &isnull);
|
||||||
if (null_n)
|
if (isnull)
|
||||||
continue; /* ignore NULL usernames */
|
continue; /* ignore NULL groupnames */
|
||||||
str_n = DatumGetCString(DirectFunctionCall1(nameout, datum_n));
|
groname = (char *) DatumGetName(datum);
|
||||||
|
|
||||||
datum_p = heap_getattr(tuple, Anum_pg_shadow_passwd, dsc, &null_p);
|
grolist_datum = heap_getattr(tuple, Anum_pg_group_grolist, dsc, &isnull);
|
||||||
|
/* Ignore NULL group lists */
|
||||||
|
if (isnull)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
grolist_p = DatumGetIdListP(grolist_datum);
|
||||||
/*
|
/*
|
||||||
* It can be argued that people having a null password shouldn't
|
* Check for illegal characters in the group name.
|
||||||
* be allowed to connect under password authentication, because
|
|
||||||
* they need to have a password set up first. If you think
|
|
||||||
* assuming an empty password in that case is better, change this
|
|
||||||
* logic to look something like the code for valuntil.
|
|
||||||
*/
|
*/
|
||||||
if (null_p)
|
i = strcspn(groname, "\n");
|
||||||
|
if (groname[i] != '\0')
|
||||||
{
|
{
|
||||||
pfree(str_n);
|
elog(LOG, "Invalid group name '%s'", groname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
str_p = DatumGetCString(DirectFunctionCall1(textout, datum_p));
|
|
||||||
|
|
||||||
datum_v = heap_getattr(tuple, Anum_pg_shadow_valuntil, dsc, &null_v);
|
/* be sure the IdList is not toasted */
|
||||||
if (null_v)
|
/* scan it */
|
||||||
str_v = pstrdup("\\N");
|
num = IDLIST_NUM(grolist_p);
|
||||||
else
|
aidp = IDLIST_DAT(grolist_p);
|
||||||
str_v = DatumGetCString(DirectFunctionCall1(nabstimeout, datum_v));
|
for (i = 0; i < num; ++i)
|
||||||
|
{
|
||||||
|
tuple = SearchSysCache(SHADOWSYSID,
|
||||||
|
PointerGetDatum(aidp[i]),
|
||||||
|
0, 0, 0);
|
||||||
|
if (HeapTupleIsValid(tuple))
|
||||||
|
{
|
||||||
|
usename = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for illegal characters in the username and password.
|
* Check for illegal characters in the user name.
|
||||||
*/
|
*/
|
||||||
i = strcspn(str_n, CRYPT_PWD_FILE_SEPSTR "\n");
|
j = strcspn(usename, "\n");
|
||||||
if (str_n[i] != '\0')
|
if (usename[j] != '\0')
|
||||||
elog(ERROR, "Invalid user name '%s'", str_n);
|
{
|
||||||
i = strcspn(str_p, CRYPT_PWD_FILE_SEPSTR "\n");
|
elog(LOG, "Invalid user name '%s'", usename);
|
||||||
if (str_p[i] != '\0')
|
continue;
|
||||||
elog(ERROR, "Invalid user password '%s'", str_p);
|
}
|
||||||
|
|
||||||
/*
|
/* File format is:
|
||||||
* The extra columns we emit here are not really necessary. To
|
* "dbname" "user1","user2","user3"
|
||||||
* remove them, the parser in backend/libpq/crypt.c would need to
|
* This matches pg_hba.conf.
|
||||||
* be adjusted.
|
*/
|
||||||
*/
|
if (first_user)
|
||||||
fprintf(fp,
|
{
|
||||||
"%s"
|
fputs_quote(groname, fp);
|
||||||
CRYPT_PWD_FILE_SEPSTR
|
fputs("\t", fp);
|
||||||
"0"
|
}
|
||||||
CRYPT_PWD_FILE_SEPSTR
|
else
|
||||||
"x"
|
fputs(" ", fp);
|
||||||
CRYPT_PWD_FILE_SEPSTR
|
|
||||||
"x"
|
|
||||||
CRYPT_PWD_FILE_SEPSTR
|
|
||||||
"x"
|
|
||||||
CRYPT_PWD_FILE_SEPSTR
|
|
||||||
"x"
|
|
||||||
CRYPT_PWD_FILE_SEPSTR
|
|
||||||
"%s"
|
|
||||||
CRYPT_PWD_FILE_SEPSTR
|
|
||||||
"%s\n",
|
|
||||||
str_n,
|
|
||||||
str_p,
|
|
||||||
str_v);
|
|
||||||
|
|
||||||
pfree(str_n);
|
first_user = false;
|
||||||
pfree(str_p);
|
fputs_quote(usename, fp);
|
||||||
pfree(str_v);
|
|
||||||
|
ReleaseSysCache(tuple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!first_user)
|
||||||
|
fputs("\n", fp);
|
||||||
|
/* if IdList was toasted, free detoasted copy */
|
||||||
|
if ((Pointer) grolist_p != DatumGetPointer(grolist_datum))
|
||||||
|
pfree(grolist_p);
|
||||||
}
|
}
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
|
|
||||||
@ -178,29 +234,154 @@ write_password_file(Relation rel)
|
|||||||
|
|
||||||
pfree((void *) tempname);
|
pfree((void *) tempname);
|
||||||
pfree((void *) filename);
|
pfree((void *) filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write_password_file for trigger update_pg_pwd_and_pg_group
|
||||||
|
*
|
||||||
|
* copy the modified contents of pg_shadow to a file used by the postmaster
|
||||||
|
* for user authentication. The file is stored as $PGDATA/global/pg_pwd.
|
||||||
|
*
|
||||||
|
* This function set is both a trigger function for direct updates to pg_shadow
|
||||||
|
* as well as being called directly from create/alter/drop user.
|
||||||
|
*
|
||||||
|
* We raise an error to force transaction rollback if we detect an illegal
|
||||||
|
* username or password --- illegal being defined as values that would
|
||||||
|
* mess up the pg_pwd parser.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
write_user_file(Relation urel)
|
||||||
|
{
|
||||||
|
char *filename,
|
||||||
|
*tempname;
|
||||||
|
int bufsize;
|
||||||
|
FILE *fp;
|
||||||
|
mode_t oumask;
|
||||||
|
HeapScanDesc scan;
|
||||||
|
HeapTuple tuple;
|
||||||
|
TupleDesc dsc = RelationGetDescr(urel);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Signal the postmaster to reload its password-file cache.
|
* Create a temporary filename to be renamed later. This prevents the
|
||||||
|
* backend from clobbering the pg_pwd file while the postmaster might
|
||||||
|
* be reading from it.
|
||||||
*/
|
*/
|
||||||
SendPostmasterSignal(PMSIGNAL_PASSWORD_CHANGE);
|
filename = user_getfilename();
|
||||||
|
bufsize = strlen(filename) + 12;
|
||||||
|
tempname = (char *) palloc(bufsize);
|
||||||
|
|
||||||
|
snprintf(tempname, bufsize, "%s.%d", filename, MyProcPid);
|
||||||
|
oumask = umask((mode_t) 077);
|
||||||
|
fp = AllocateFile(tempname, "w");
|
||||||
|
umask(oumask);
|
||||||
|
if (fp == NULL)
|
||||||
|
elog(ERROR, "write_password_file: unable to write %s: %m", tempname);
|
||||||
|
|
||||||
|
/* read table */
|
||||||
|
scan = heap_beginscan(urel, false, SnapshotSelf, 0, NULL);
|
||||||
|
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||||
|
{
|
||||||
|
Datum datum;
|
||||||
|
bool isnull;
|
||||||
|
char *usename,
|
||||||
|
*passwd,
|
||||||
|
*valuntil;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
datum = heap_getattr(tuple, Anum_pg_shadow_usename, dsc, &isnull);
|
||||||
|
if (isnull)
|
||||||
|
continue; /* ignore NULL usernames */
|
||||||
|
usename = (char *) DatumGetName(datum);
|
||||||
|
|
||||||
|
datum = heap_getattr(tuple, Anum_pg_shadow_passwd, dsc, &isnull);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It can be argued that people having a null password shouldn't
|
||||||
|
* be allowed to connect under password authentication, because
|
||||||
|
* they need to have a password set up first. If you think
|
||||||
|
* assuming an empty password in that case is better, change this
|
||||||
|
* logic to look something like the code for valuntil.
|
||||||
|
*/
|
||||||
|
if (isnull)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
passwd = DatumGetCString(DirectFunctionCall1(textout, datum));
|
||||||
|
|
||||||
|
datum = heap_getattr(tuple, Anum_pg_shadow_valuntil, dsc, &isnull);
|
||||||
|
if (isnull)
|
||||||
|
valuntil = pstrdup("");
|
||||||
|
else
|
||||||
|
valuntil = DatumGetCString(DirectFunctionCall1(nabstimeout, datum));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for illegal characters in the username and password.
|
||||||
|
*/
|
||||||
|
i = strcspn(usename, "\n");
|
||||||
|
if (usename[i] != '\0')
|
||||||
|
elog(ERROR, "Invalid user name '%s'", usename);
|
||||||
|
i = strcspn(passwd, "\n");
|
||||||
|
if (passwd[i] != '\0')
|
||||||
|
elog(ERROR, "Invalid user password '%s'", passwd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The extra columns we emit here are not really necessary. To
|
||||||
|
* remove them, the parser in backend/libpq/crypt.c would need to
|
||||||
|
* be adjusted.
|
||||||
|
*/
|
||||||
|
fputs_quote(usename, fp);
|
||||||
|
fputs(" ", fp);
|
||||||
|
fputs_quote(passwd, fp);
|
||||||
|
fputs(" ", fp);
|
||||||
|
fputs_quote(valuntil, fp);
|
||||||
|
|
||||||
|
pfree(passwd);
|
||||||
|
pfree(valuntil);
|
||||||
|
}
|
||||||
|
heap_endscan(scan);
|
||||||
|
|
||||||
|
fflush(fp);
|
||||||
|
if (ferror(fp))
|
||||||
|
elog(ERROR, "%s: %m", tempname);
|
||||||
|
FreeFile(fp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rename the temp file to its final name, deleting the old pg_pwd. We
|
||||||
|
* expect that rename(2) is an atomic action.
|
||||||
|
*/
|
||||||
|
if (rename(tempname, filename))
|
||||||
|
elog(ERROR, "rename %s to %s: %m", tempname, filename);
|
||||||
|
|
||||||
|
pfree((void *) tempname);
|
||||||
|
pfree((void *) filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This is the wrapper for triggers. */
|
/* This is the wrapper for triggers. */
|
||||||
Datum
|
Datum
|
||||||
update_pg_pwd(PG_FUNCTION_ARGS)
|
update_pg_pwd_and_pg_group(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* ExclusiveLock ensures no one modifies pg_shadow while we read it,
|
* ExclusiveLock ensures no one modifies pg_shadow while we read it,
|
||||||
* and that only one backend rewrites the flat file at a time. It's
|
* and that only one backend rewrites the flat file at a time. It's
|
||||||
* OK to allow normal reads of pg_shadow in parallel, however.
|
* OK to allow normal reads of pg_shadow in parallel, however.
|
||||||
*/
|
*/
|
||||||
Relation rel = heap_openr(ShadowRelationName, ExclusiveLock);
|
Relation urel = heap_openr(ShadowRelationName, ExclusiveLock);
|
||||||
|
Relation grel = heap_openr(GroupRelationName, ExclusiveLock);
|
||||||
|
|
||||||
write_password_file(rel);
|
write_user_file(urel);
|
||||||
|
write_group_file(urel, grel);
|
||||||
/* OK to release lock, since we did not modify the relation */
|
/* OK to release lock, since we did not modify the relation */
|
||||||
heap_close(rel, ExclusiveLock);
|
heap_close(grel, ExclusiveLock);
|
||||||
|
heap_close(urel, ExclusiveLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal the postmaster to reload its password & group-file cache.
|
||||||
|
*/
|
||||||
|
SendPostmasterSignal(PMSIGNAL_PASSWORD_CHANGE);
|
||||||
|
|
||||||
return PointerGetDatum(NULL);
|
return PointerGetDatum(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,15 +626,15 @@ CreateUser(CreateUserStmt *stmt)
|
|||||||
AlterGroup(&ags, "CREATE USER");
|
AlterGroup(&ags, "CREATE USER");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Write the updated pg_shadow data to the flat password file.
|
|
||||||
*/
|
|
||||||
write_password_file(pg_shadow_rel);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we can clean up; but keep lock until commit.
|
* Now we can clean up; but keep lock until commit.
|
||||||
*/
|
*/
|
||||||
heap_close(pg_shadow_rel, NoLock);
|
heap_close(pg_shadow_rel, NoLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the updated pg_shadow and pg_group data to the flat file.
|
||||||
|
*/
|
||||||
|
update_pg_pwd_and_pg_group(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -679,15 +860,15 @@ AlterUser(AlterUserStmt *stmt)
|
|||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
heap_freetuple(new_tuple);
|
heap_freetuple(new_tuple);
|
||||||
|
|
||||||
/*
|
|
||||||
* Write the updated pg_shadow data to the flat password file.
|
|
||||||
*/
|
|
||||||
write_password_file(pg_shadow_rel);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we can clean up.
|
* Now we can clean up.
|
||||||
*/
|
*/
|
||||||
heap_close(pg_shadow_rel, NoLock);
|
heap_close(pg_shadow_rel, NoLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the updated pg_shadow and pg_group data to the flat file.
|
||||||
|
*/
|
||||||
|
update_pg_pwd_and_pg_group(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -733,7 +914,7 @@ AlterUserSet(AlterUserSetStmt *stmt)
|
|||||||
{
|
{
|
||||||
Datum datum;
|
Datum datum;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
ArrayType *a;
|
ArrayType *array;
|
||||||
|
|
||||||
repl_null[Anum_pg_shadow_useconfig-1] = ' ';
|
repl_null[Anum_pg_shadow_useconfig-1] = ' ';
|
||||||
|
|
||||||
@ -741,17 +922,17 @@ AlterUserSet(AlterUserSetStmt *stmt)
|
|||||||
Anum_pg_shadow_useconfig, &isnull);
|
Anum_pg_shadow_useconfig, &isnull);
|
||||||
|
|
||||||
if (valuestr)
|
if (valuestr)
|
||||||
a = GUCArrayAdd(isnull
|
array = GUCArrayAdd(isnull
|
||||||
? NULL
|
? NULL
|
||||||
: (ArrayType *) pg_detoast_datum((struct varlena *)datum),
|
: (ArrayType *) pg_detoast_datum((struct varlena *)datum),
|
||||||
stmt->variable, valuestr);
|
stmt->variable, valuestr);
|
||||||
else
|
else
|
||||||
a = GUCArrayDelete(isnull
|
array = GUCArrayDelete(isnull
|
||||||
? NULL
|
? NULL
|
||||||
: (ArrayType *) pg_detoast_datum((struct varlena *)datum),
|
: (ArrayType *) pg_detoast_datum((struct varlena *)datum),
|
||||||
stmt->variable);
|
stmt->variable);
|
||||||
|
|
||||||
repl_val[Anum_pg_shadow_useconfig-1] = PointerGetDatum(a);
|
repl_val[Anum_pg_shadow_useconfig-1] = PointerGetDatum(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
newtuple = heap_modifytuple(oldtuple, rel, repl_val, repl_null, repl_repl);
|
newtuple = heap_modifytuple(oldtuple, rel, repl_val, repl_null, repl_repl);
|
||||||
@ -846,7 +1027,7 @@ DropUser(DropUserStmt *stmt)
|
|||||||
datum = heap_getattr(tmp_tuple, Anum_pg_database_datname,
|
datum = heap_getattr(tmp_tuple, Anum_pg_database_datname,
|
||||||
pg_dsc, &null);
|
pg_dsc, &null);
|
||||||
Assert(!null);
|
Assert(!null);
|
||||||
dbname = DatumGetCString(DirectFunctionCall1(nameout, datum));
|
dbname = (char *) DatumGetName(datum);
|
||||||
elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s",
|
elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s",
|
||||||
user, dbname,
|
user, dbname,
|
||||||
(length(stmt->users) > 1) ? " (no users removed)" : "");
|
(length(stmt->users) > 1) ? " (no users removed)" : "");
|
||||||
@ -900,15 +1081,15 @@ DropUser(DropUserStmt *stmt)
|
|||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Write the updated pg_shadow data to the flat password file.
|
|
||||||
*/
|
|
||||||
write_password_file(pg_shadow_rel);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we can clean up.
|
* Now we can clean up.
|
||||||
*/
|
*/
|
||||||
heap_close(pg_shadow_rel, NoLock);
|
heap_close(pg_shadow_rel, NoLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the updated pg_shadow and pg_group data to the flat file.
|
||||||
|
*/
|
||||||
|
update_pg_pwd_and_pg_group(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1111,6 +1292,11 @@ CreateGroup(CreateGroupStmt *stmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
heap_close(pg_group_rel, NoLock);
|
heap_close(pg_group_rel, NoLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the updated pg_shadow and pg_group data to the flat file.
|
||||||
|
*/
|
||||||
|
update_pg_pwd_and_pg_group(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1366,7 +1552,15 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
|
|||||||
|
|
||||||
ReleaseSysCache(group_tuple);
|
ReleaseSysCache(group_tuple);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the updated pg_shadow and pg_group data to the flat files.
|
||||||
|
*/
|
||||||
heap_close(pg_group_rel, NoLock);
|
heap_close(pg_group_rel, NoLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the updated pg_shadow and pg_group data to the flat file.
|
||||||
|
*/
|
||||||
|
update_pg_pwd_and_pg_group(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1419,4 +1613,9 @@ DropGroup(DropGroupStmt *stmt)
|
|||||||
elog(ERROR, "DROP GROUP: group \"%s\" does not exist", stmt->name);
|
elog(ERROR, "DROP GROUP: group \"%s\" does not exist", stmt->name);
|
||||||
|
|
||||||
heap_close(pg_group_rel, NoLock);
|
heap_close(pg_group_rel, NoLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the updated pg_shadow and pg_group data to the flat file.
|
||||||
|
*/
|
||||||
|
update_pg_pwd_and_pg_group(NULL);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# Makefile for libpq subsystem (backend half of libpq interface)
|
# Makefile for libpq subsystem (backend half of libpq interface)
|
||||||
#
|
#
|
||||||
# IDENTIFICATION
|
# IDENTIFICATION
|
||||||
# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.29 2002/03/04 01:46:02 tgl Exp $
|
# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.30 2002/04/04 04:25:46 momjian Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -14,9 +14,7 @@ include $(top_builddir)/src/Makefile.global
|
|||||||
|
|
||||||
# be-fsstubs is here for historical reasons, probably belongs elsewhere
|
# be-fsstubs is here for historical reasons, probably belongs elsewhere
|
||||||
|
|
||||||
OBJS = be-fsstubs.o \
|
OBJS = be-fsstubs.o auth.o crypt.o hba.o md5.o pqcomm.o pqformat.o pqsignal.o
|
||||||
auth.o crypt.o hba.o md5.o password.o \
|
|
||||||
pqcomm.o pqformat.o pqsignal.o
|
|
||||||
|
|
||||||
|
|
||||||
all: SUBSYS.o
|
all: SUBSYS.o
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.79 2002/03/05 07:57:45 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.80 2002/04/04 04:25:47 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -34,7 +34,6 @@
|
|||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
|
|
||||||
static void sendAuthRequest(Port *port, AuthRequest areq);
|
static void sendAuthRequest(Port *port, AuthRequest areq);
|
||||||
static int checkPassword(Port *port, char *user, char *password);
|
|
||||||
static int old_be_recvauth(Port *port);
|
static int old_be_recvauth(Port *port);
|
||||||
static int map_old_to_new(Port *port, UserAuth old, int status);
|
static int map_old_to_new(Port *port, UserAuth old, int status);
|
||||||
static void auth_failed(Port *port, int status);
|
static void auth_failed(Port *port, int status);
|
||||||
@ -381,7 +380,7 @@ recv_and_check_passwordv0(Port *port)
|
|||||||
saved = port->auth_method;
|
saved = port->auth_method;
|
||||||
port->auth_method = uaPassword;
|
port->auth_method = uaPassword;
|
||||||
|
|
||||||
status = checkPassword(port, user, password);
|
status = md5_crypt_verify(port, user, password);
|
||||||
|
|
||||||
port->auth_method = saved;
|
port->auth_method = saved;
|
||||||
|
|
||||||
@ -663,7 +662,7 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, struct pam_re
|
|||||||
|
|
||||||
initStringInfo(&buf);
|
initStringInfo(&buf);
|
||||||
pq_getstr(&buf);
|
pq_getstr(&buf);
|
||||||
|
|
||||||
/* Do not echo failed password to logs, for security. */
|
/* Do not echo failed password to logs, for security. */
|
||||||
elog(DEBUG5, "received PAM packet");
|
elog(DEBUG5, "received PAM packet");
|
||||||
|
|
||||||
@ -810,26 +809,13 @@ recv_and_check_password_packet(Port *port)
|
|||||||
/* Do not echo failed password to logs, for security. */
|
/* Do not echo failed password to logs, for security. */
|
||||||
elog(DEBUG5, "received password packet");
|
elog(DEBUG5, "received password packet");
|
||||||
|
|
||||||
result = checkPassword(port, port->user, buf.data);
|
result = md5_crypt_verify(port, port->user, buf.data);
|
||||||
|
|
||||||
pfree(buf.data);
|
pfree(buf.data);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle `password' and `crypt' records. If an auth argument was
|
|
||||||
* specified, use the respective file. Else use pg_shadow passwords.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
checkPassword(Port *port, char *user, char *password)
|
|
||||||
{
|
|
||||||
if (port->auth_arg[0] != '\0')
|
|
||||||
return verify_password(port, user, password);
|
|
||||||
|
|
||||||
return md5_crypt_verify(port, user, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Server demux routine for incoming authentication information for protocol
|
* Server demux routine for incoming authentication information for protocol
|
||||||
* version 0.
|
* version 0.
|
||||||
|
@ -9,13 +9,12 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.44 2002/03/04 01:46:03 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.45 2002/04/04 04:25:47 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef HAVE_CRYPT_H
|
#ifdef HAVE_CRYPT_H
|
||||||
#include <crypt.h>
|
#include <crypt.h>
|
||||||
@ -25,231 +24,10 @@
|
|||||||
#include "libpq/libpq.h"
|
#include "libpq/libpq.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "storage/fd.h"
|
#include "storage/fd.h"
|
||||||
|
#include "nodes/pg_list.h"
|
||||||
#include "utils/nabstime.h"
|
#include "utils/nabstime.h"
|
||||||
|
|
||||||
|
|
||||||
#define CRYPT_PWD_FILE "pg_pwd"
|
|
||||||
|
|
||||||
|
|
||||||
static char **pwd_cache = NULL;
|
|
||||||
static int pwd_cache_count = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* crypt_getpwdfilename --- get full pathname of password file
|
|
||||||
*
|
|
||||||
* Note that result string is palloc'd, and should be freed by the caller.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
crypt_getpwdfilename(void)
|
|
||||||
{
|
|
||||||
int bufsize;
|
|
||||||
char *pfnam;
|
|
||||||
|
|
||||||
bufsize = strlen(DataDir) + 8 + strlen(CRYPT_PWD_FILE) + 1;
|
|
||||||
pfnam = (char *) palloc(bufsize);
|
|
||||||
snprintf(pfnam, bufsize, "%s/global/%s", DataDir, CRYPT_PWD_FILE);
|
|
||||||
|
|
||||||
return pfnam;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open the password file if possible (return NULL if not)
|
|
||||||
*/
|
|
||||||
static FILE *
|
|
||||||
crypt_openpwdfile(void)
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
FILE *pwdfile;
|
|
||||||
|
|
||||||
filename = crypt_getpwdfilename();
|
|
||||||
pwdfile = AllocateFile(filename, "r");
|
|
||||||
|
|
||||||
if (pwdfile == NULL && errno != ENOENT)
|
|
||||||
elog(LOG, "could not open %s: %m", filename);
|
|
||||||
|
|
||||||
pfree(filename);
|
|
||||||
|
|
||||||
return pwdfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare two password-file lines on the basis of their usernames.
|
|
||||||
*
|
|
||||||
* Can also be used to compare just a username against a password-file
|
|
||||||
* line (for bsearch).
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
compar_user(const void *user_a, const void *user_b)
|
|
||||||
{
|
|
||||||
char *login_a;
|
|
||||||
char *login_b;
|
|
||||||
int len_a,
|
|
||||||
len_b,
|
|
||||||
result;
|
|
||||||
|
|
||||||
login_a = *((char **) user_a);
|
|
||||||
login_b = *((char **) user_b);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We only really want to compare the user logins which are first and
|
|
||||||
* are terminated by CRYPT_PWD_FILE_SEPSTR. (NB: this code
|
|
||||||
* effectively assumes that CRYPT_PWD_FILE_SEPSTR is just one char.)
|
|
||||||
*/
|
|
||||||
len_a = strcspn(login_a, CRYPT_PWD_FILE_SEPSTR);
|
|
||||||
len_b = strcspn(login_b, CRYPT_PWD_FILE_SEPSTR);
|
|
||||||
|
|
||||||
result = strncmp(login_a, login_b, Min(len_a, len_b));
|
|
||||||
|
|
||||||
if (result == 0) /* one could be a prefix of the other */
|
|
||||||
result = (len_a - len_b);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Load or reload the password-file cache
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
load_password_cache(void)
|
|
||||||
{
|
|
||||||
FILE *pwd_file;
|
|
||||||
char buffer[1024];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If for some reason we fail to open the password file, preserve the
|
|
||||||
* old cache contents; this seems better than dropping the cache if,
|
|
||||||
* say, we are temporarily out of filetable slots.
|
|
||||||
*/
|
|
||||||
if (!(pwd_file = crypt_openpwdfile()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* free any old data */
|
|
||||||
if (pwd_cache)
|
|
||||||
{
|
|
||||||
while (--pwd_cache_count >= 0)
|
|
||||||
pfree(pwd_cache[pwd_cache_count]);
|
|
||||||
pfree(pwd_cache);
|
|
||||||
pwd_cache = NULL;
|
|
||||||
pwd_cache_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the file and store its lines in current memory context, which
|
|
||||||
* we expect will be PostmasterContext. That context will live as
|
|
||||||
* long as we need the cache to live, ie, until just after each
|
|
||||||
* postmaster child has completed client authentication.
|
|
||||||
*/
|
|
||||||
while (fgets(buffer, sizeof(buffer), pwd_file) != NULL)
|
|
||||||
{
|
|
||||||
int blen;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We must remove the return char at the end of the string, as
|
|
||||||
* this will affect the correct parsing of the password entry.
|
|
||||||
*/
|
|
||||||
if (buffer[(blen = strlen(buffer) - 1)] == '\n')
|
|
||||||
buffer[blen] = '\0';
|
|
||||||
|
|
||||||
if (pwd_cache == NULL)
|
|
||||||
pwd_cache = (char **)
|
|
||||||
palloc(sizeof(char *) * (pwd_cache_count + 1));
|
|
||||||
else
|
|
||||||
pwd_cache = (char **)
|
|
||||||
repalloc((void *) pwd_cache,
|
|
||||||
sizeof(char *) * (pwd_cache_count + 1));
|
|
||||||
pwd_cache[pwd_cache_count++] = pstrdup(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeFile(pwd_file);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now sort the entries in the cache for faster searching later.
|
|
||||||
*/
|
|
||||||
qsort((void *) pwd_cache, pwd_cache_count, sizeof(char *), compar_user);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse a line of the password file to extract password and valid-until date.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
crypt_parsepwdentry(char *buffer, char **pwd, char **valdate)
|
|
||||||
{
|
|
||||||
char *parse = buffer;
|
|
||||||
int count,
|
|
||||||
i;
|
|
||||||
|
|
||||||
*pwd = NULL;
|
|
||||||
*valdate = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* skip to the password field
|
|
||||||
*/
|
|
||||||
for (i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
parse += strcspn(parse, CRYPT_PWD_FILE_SEPSTR);
|
|
||||||
if (*parse == '\0')
|
|
||||||
return false;
|
|
||||||
parse++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* store a copy of user password to return
|
|
||||||
*/
|
|
||||||
count = strcspn(parse, CRYPT_PWD_FILE_SEPSTR);
|
|
||||||
*pwd = (char *) palloc(count + 1);
|
|
||||||
memcpy(*pwd, parse, count);
|
|
||||||
(*pwd)[count] = '\0';
|
|
||||||
parse += count;
|
|
||||||
if (*parse == '\0')
|
|
||||||
{
|
|
||||||
pfree(*pwd);
|
|
||||||
*pwd = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
parse++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* store a copy of the date login becomes invalid
|
|
||||||
*/
|
|
||||||
count = strcspn(parse, CRYPT_PWD_FILE_SEPSTR);
|
|
||||||
*valdate = (char *) palloc(count + 1);
|
|
||||||
memcpy(*valdate, parse, count);
|
|
||||||
(*valdate)[count] = '\0';
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lookup a username in the password-file cache,
|
|
||||||
* return his password and valid-until date.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
crypt_getloginfo(const char *user, char **passwd, char **valuntil)
|
|
||||||
{
|
|
||||||
*passwd = NULL;
|
|
||||||
*valuntil = NULL;
|
|
||||||
|
|
||||||
if (pwd_cache)
|
|
||||||
{
|
|
||||||
char **pwd_entry;
|
|
||||||
|
|
||||||
pwd_entry = (char **) bsearch((void *) &user,
|
|
||||||
(void *) pwd_cache,
|
|
||||||
pwd_cache_count,
|
|
||||||
sizeof(char *),
|
|
||||||
compar_user);
|
|
||||||
if (pwd_entry)
|
|
||||||
{
|
|
||||||
if (crypt_parsepwdentry(*pwd_entry, passwd, valuntil))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int
|
int
|
||||||
md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
|
md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
|
||||||
{
|
{
|
||||||
@ -257,10 +35,14 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass)
|
|||||||
*valuntil,
|
*valuntil,
|
||||||
*crypt_pwd;
|
*crypt_pwd;
|
||||||
int retval = STATUS_ERROR;
|
int retval = STATUS_ERROR;
|
||||||
|
List **line;
|
||||||
|
|
||||||
if (!crypt_getloginfo(user, &passwd, &valuntil))
|
if ((line = get_user_line(user)) == NULL)
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
|
|
||||||
|
passwd = lfirst(lnext(lnext(*line)));
|
||||||
|
valuntil = lfirst(lnext(lnext(lnext(*line))));
|
||||||
|
|
||||||
if (passwd == NULL || *passwd == '\0')
|
if (passwd == NULL || *passwd == '\0')
|
||||||
{
|
{
|
||||||
if (passwd)
|
if (passwd)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
|
||||||
*
|
|
||||||
* $Id: password.c,v 1.41 2002/03/04 01:46:03 tgl Exp $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "postgres.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_CRYPT_H
|
|
||||||
#include <crypt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "libpq/libpq.h"
|
|
||||||
#include "libpq/password.h"
|
|
||||||
#include "libpq/crypt.h"
|
|
||||||
#include "miscadmin.h"
|
|
||||||
#include "storage/fd.h"
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
verify_password(const Port *port, const char *user, const char *password)
|
|
||||||
{
|
|
||||||
char *pw_file_fullname;
|
|
||||||
FILE *pw_file;
|
|
||||||
|
|
||||||
pw_file_fullname = (char *) palloc(strlen(DataDir) + strlen(port->auth_arg) + 2);
|
|
||||||
strcpy(pw_file_fullname, DataDir);
|
|
||||||
strcat(pw_file_fullname, "/");
|
|
||||||
strcat(pw_file_fullname, port->auth_arg);
|
|
||||||
|
|
||||||
pw_file = AllocateFile(pw_file_fullname, PG_BINARY_R);
|
|
||||||
if (!pw_file)
|
|
||||||
{
|
|
||||||
elog(LOG, "verify_password: Unable to open password file \"%s\": %m",
|
|
||||||
pw_file_fullname);
|
|
||||||
|
|
||||||
pfree(pw_file_fullname);
|
|
||||||
|
|
||||||
return STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
pfree(pw_file_fullname);
|
|
||||||
|
|
||||||
while (!feof(pw_file))
|
|
||||||
{
|
|
||||||
char pw_file_line[255],
|
|
||||||
*p,
|
|
||||||
*test_user,
|
|
||||||
*test_pw;
|
|
||||||
|
|
||||||
if (fgets(pw_file_line, sizeof(pw_file_line), pw_file) == NULL)
|
|
||||||
pw_file_line[0] = '\0';
|
|
||||||
/* kill the newline */
|
|
||||||
if (strlen(pw_file_line) > 0 &&
|
|
||||||
pw_file_line[strlen(pw_file_line) - 1] == '\n')
|
|
||||||
pw_file_line[strlen(pw_file_line) - 1] = '\0';
|
|
||||||
|
|
||||||
p = pw_file_line;
|
|
||||||
|
|
||||||
test_user = strtok(p, ":");
|
|
||||||
if (!test_user || test_user[0] == '\0')
|
|
||||||
continue;
|
|
||||||
test_pw = strtok(NULL, ":");
|
|
||||||
|
|
||||||
if (strcmp(user, test_user) == 0)
|
|
||||||
{
|
|
||||||
/* we're outta here one way or the other, so close file */
|
|
||||||
FreeFile(pw_file);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the password is empty or "+" then we use the regular
|
|
||||||
* pg_shadow passwords. If we use crypt then we have to use
|
|
||||||
* pg_shadow passwords no matter what. This is because the
|
|
||||||
* current code needs non-encrypted passwords to encrypt with
|
|
||||||
* a random salt.
|
|
||||||
*/
|
|
||||||
if (port->auth_method == uaMD5 ||
|
|
||||||
port->auth_method == uaCrypt ||
|
|
||||||
test_pw == NULL ||
|
|
||||||
test_pw[0] == '\0' ||
|
|
||||||
strcmp(test_pw, "+") == 0)
|
|
||||||
return md5_crypt_verify(port, user, password);
|
|
||||||
|
|
||||||
/* external password file is crypt-only */
|
|
||||||
if (strcmp(crypt(password, test_pw), test_pw) == 0)
|
|
||||||
{
|
|
||||||
/* it matched. */
|
|
||||||
return STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
elog(LOG, "verify_password: password mismatch for '%s'",
|
|
||||||
user);
|
|
||||||
|
|
||||||
return STATUS_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeFile(pw_file);
|
|
||||||
|
|
||||||
elog(LOG, "verify_password: user '%s' not found in password file",
|
|
||||||
user);
|
|
||||||
|
|
||||||
return STATUS_ERROR;
|
|
||||||
}
|
|
@ -42,22 +42,36 @@
|
|||||||
#
|
#
|
||||||
# Format:
|
# Format:
|
||||||
#
|
#
|
||||||
# host DBNAME IP_ADDRESS ADDRESS_MASK AUTH_TYPE [AUTH_ARGUMENT]
|
# host DATABASE USER IP_ADDRESS MASK AUTH_TYPE
|
||||||
#
|
#
|
||||||
# DBNAME can be:
|
# DATABASE can be:
|
||||||
# o a database name
|
# o a database name
|
||||||
# o "all", which means the record matches all databases
|
# o "sameuser", which means a user can only access a database with the
|
||||||
# o "sameuser", which means users can only access databases whose name
|
# same name as their user name
|
||||||
# is the same as their username
|
# o "samegroup", which means a user can only access databases when they
|
||||||
|
# are members of a group with the same name as the database name
|
||||||
|
# o "all", which matches all databases
|
||||||
|
# o a list of database names, separated by commas
|
||||||
|
# o a file name containing database names, starting with '@'
|
||||||
#
|
#
|
||||||
# IP_ADDRESS and ADDRESS_MASK are standard dotted decimal IP address and
|
# USER can be:
|
||||||
|
# o a user name
|
||||||
|
# o "all", which matches all users
|
||||||
|
# o a list of user names, separated by commas
|
||||||
|
# o a group name, starting with '+'
|
||||||
|
# o a file name containing user names, starting with '@'
|
||||||
|
#
|
||||||
|
# Files read using '@' can contain comma-separated database/user names,
|
||||||
|
# or one name per line. The files can also contain comments using '#'.
|
||||||
|
#
|
||||||
|
# IP_ADDRESS and MASK are standard dotted decimal IP address and
|
||||||
# mask values. IP addresses can only be specified numerically, not as
|
# mask values. IP addresses can only be specified numerically, not as
|
||||||
# domain or host names.
|
# domain or host names.
|
||||||
#
|
#
|
||||||
# Do not prevent the superuser from accessing the template1 database.
|
# Do not prevent the superuser from accessing the template1 database.
|
||||||
# Various utility commands need access to template1.
|
# Various utility commands need access to template1.
|
||||||
#
|
#
|
||||||
# AUTH_TYPE and AUTH_ARGUMENT are described below.
|
# AUTH_TYPE is described below.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# hostssl
|
# hostssl
|
||||||
@ -65,10 +79,8 @@
|
|||||||
#
|
#
|
||||||
# The format of this record is identical to "host".
|
# The format of this record is identical to "host".
|
||||||
#
|
#
|
||||||
#
|
# It specifies hosts that require connection via secure SSL. "host"
|
||||||
#
|
# allows SSL connections too, but "hostssl" requires SSL-secured
|
||||||
# It specifies hosts that required connection via secure SSL. "host"
|
|
||||||
# records allow SSL connections too, but "hostssl" only allows SSL-secured
|
|
||||||
# connections.
|
# connections.
|
||||||
#
|
#
|
||||||
# This keyword is only available if the server was compiled with SSL
|
# This keyword is only available if the server was compiled with SSL
|
||||||
@ -82,10 +94,10 @@
|
|||||||
# connections. Without this record, UNIX-socket connections are disallowed
|
# connections. Without this record, UNIX-socket connections are disallowed
|
||||||
#
|
#
|
||||||
# Format:
|
# Format:
|
||||||
# local DBNAME AUTH_TYPE [AUTH_ARGUMENT]
|
# local DATABASE USER AUTH_TYPE
|
||||||
#
|
#
|
||||||
# This format is identical to the "host" record type except there are no
|
# This format is identical to the "host" record type except there are no
|
||||||
# IP_ADDRESS and ADDRESS_MASK fields.
|
# IP_ADDRESS and MASK fields.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -96,57 +108,38 @@
|
|||||||
# has an AUTH_TYPE.
|
# has an AUTH_TYPE.
|
||||||
#
|
#
|
||||||
# trust:
|
# trust:
|
||||||
# No authentication is done. Any valid username is accepted,
|
# No authentication is done. Any valid user name is accepted,
|
||||||
# including the PostgreSQL superuser. This option should
|
# including the PostgreSQL superuser. This option should
|
||||||
# be used only for hosts where all users are trusted.
|
# be used only for hosts where all users are trusted.
|
||||||
#
|
#
|
||||||
# password:
|
|
||||||
# Authentication is done by matching a password supplied
|
|
||||||
# in clear by the host. If no AUTH_ARGUMENT is used, the
|
|
||||||
# password is compared with the user's entry in the
|
|
||||||
# pg_shadow table.
|
|
||||||
#
|
|
||||||
# If AUTH_ARGUMENT is specified, the username is looked up
|
|
||||||
# in that file in the $PGDATA directory. If the username
|
|
||||||
# is found but there is no password, the password is looked
|
|
||||||
# up in pg_shadow. If a password exists in the file, it is
|
|
||||||
# used instead. These secondary files allow fine-grained
|
|
||||||
# control over who can access which databases and whether
|
|
||||||
# a non-default password is required. The same file can be
|
|
||||||
# used in multiple records for easier administration.
|
|
||||||
# Password files can be maintained with the pg_passwd(1)
|
|
||||||
# utility. Remember, these passwords override pg_shadow
|
|
||||||
# passwords. Also, such passwords are passed over the network
|
|
||||||
# in cleartext, meaning this should not be used on untrusted
|
|
||||||
# networks.
|
|
||||||
#
|
|
||||||
# md5:
|
# md5:
|
||||||
# Same as "password", except the password is encrypted over the
|
# Requires the client to supply an MD5 encrypted password for
|
||||||
# network. This method is preferable to "password" and "crypt"
|
# authentication. This is the only method that allows encrypted
|
||||||
# except for pre-7.2 clients that don't support it. NOTE: md5 can
|
# passwords to be stored in pg_shadow.
|
||||||
# use usernames stored in secondary password files but ignores
|
|
||||||
# passwords stored there. The pg_shadow password will always be
|
|
||||||
# used.
|
|
||||||
#
|
#
|
||||||
# crypt:
|
# crypt:
|
||||||
# Same as "md5", but uses crypt for pre-7.2 clients. You can
|
# Same as "md5", but uses crypt for pre-7.2 clients.
|
||||||
# not store encrypted passwords in pg_shadow if you use this
|
|
||||||
# method.
|
|
||||||
#
|
#
|
||||||
|
# password:
|
||||||
|
# Same as "md5", but the password is sent in cleartext over
|
||||||
|
# the network. This should not be used on untrusted
|
||||||
|
# networks.
|
||||||
|
#
|
||||||
# ident:
|
# ident:
|
||||||
# For TCP/IP connections, authentication is done by contacting the
|
# For TCP/IP connections, authentication is done by contacting the
|
||||||
# ident server on the client host. This is only as secure as the
|
# ident server on the client host. This is only as secure as the
|
||||||
# client machine. On machines that support unix-domain socket
|
# client machine. You must specify the map name after the 'ident'
|
||||||
# credentials (currently Linux, FreeBSD, NetBSD, and BSD/OS), this
|
# keyword. It determines how to map remote user names to
|
||||||
# method also works for "local" connections.
|
# PostgreSQL user names. If you use "sameuser", the user names are
|
||||||
|
# assumed to be identical. If not, the map name is looked up
|
||||||
|
# in the $PGDATA/pg_ident.conf file. The connection is accepted if
|
||||||
|
# that file contains an entry for this map name with the
|
||||||
|
# ident-supplied username and the requested PostgreSQL username.
|
||||||
#
|
#
|
||||||
# AUTH_ARGUMENT is required. It determines how to map remote user
|
# On machines that support unix-domain socket credentials
|
||||||
# names to PostgreSQL user names. If you use "sameuser", the user
|
# (currently Linux, FreeBSD, NetBSD, and BSD/OS), ident allows
|
||||||
# names are assumed to be the identical. If not, AUTH_ARGUMENT is
|
# reliable authentication of 'local' connections without ident
|
||||||
# assumed to be a map name found in the $PGDATA/pg_ident.conf
|
# running on the local machine.
|
||||||
# file. The connection is accepted if that file contains an entry
|
|
||||||
# for this map name with the ident-supplied username and the
|
|
||||||
# requested PostgreSQL username.
|
|
||||||
#
|
#
|
||||||
# krb4:
|
# krb4:
|
||||||
# Kerberos V4 authentication is used. Allowed only for
|
# Kerberos V4 authentication is used. Allowed only for
|
||||||
@ -157,10 +150,10 @@
|
|||||||
# TCP/IP connections, not for local UNIX-domain sockets.
|
# TCP/IP connections, not for local UNIX-domain sockets.
|
||||||
#
|
#
|
||||||
# pam:
|
# pam:
|
||||||
# Authentication is passed off to PAM (PostgreSQL must be
|
# Authentication is done by PAM using the default service name
|
||||||
# configured --with-pam), using the default service name
|
# "postgresql". You can specify your own service name by adding
|
||||||
# "postgresql" - you can specify your own service name by
|
# the service name after the 'pam' keyword. To use this option,
|
||||||
# setting AUTH_ARGUMENT to the desired service name.
|
# PostgreSQL must be configured --with-pam.
|
||||||
#
|
#
|
||||||
# reject:
|
# reject:
|
||||||
# Reject the connection. This is used to reject certain hosts
|
# Reject the connection. This is used to reject certain hosts
|
||||||
@ -177,60 +170,70 @@
|
|||||||
# Allow any user on the local system to connect to any database under any
|
# Allow any user on the local system to connect to any database under any
|
||||||
# username using Unix-domain sockets (the default for local connections):
|
# username using Unix-domain sockets (the default for local connections):
|
||||||
#
|
#
|
||||||
# TYPE DATABASE IP_ADDRESS MASK AUTH_TYPE AUTH_ARGUMENT
|
# TYPE DATABASE USER IP_ADDRESS MASK AUTH_TYPE
|
||||||
# local all trust
|
# local all all trust
|
||||||
#
|
#
|
||||||
# The same using local loopback TCP/IP connections:
|
# The same using local loopback TCP/IP connections:
|
||||||
#
|
#
|
||||||
# TYPE DATABASE IP_ADDRESS MASK AUTH_TYPE AUTH_ARGUMENT
|
# TYPE DATABASE USER IP_ADDRESS MASK AUTH_TYPE
|
||||||
# host all 127.0.0.1 255.255.255.255 trust
|
# host all all 127.0.0.1 255.255.255.255 trust
|
||||||
#
|
#
|
||||||
# Allow any user from any host with IP address 192.168.93.x to
|
# Allow any user from any host with IP address 192.168.93.x to
|
||||||
# connect to database "template1" as the same username that ident reports
|
# connect to database "template1" as the same username that ident reports
|
||||||
# for the connection (typically his Unix username):
|
# for the connection (typically his Unix username):
|
||||||
#
|
#
|
||||||
# TYPE DATABASE IP_ADDRESS MASK AUTH_TYPE AUTH_ARGUMENT
|
# TYPE DATABASE USER IP_ADDRESS MASK AUTH_TYPE
|
||||||
# host template1 192.168.93.0 255.255.255.0 ident sameuser
|
# host template1 all 192.168.93.0 255.255.255.0 ident sameuser
|
||||||
#
|
#
|
||||||
# Allow a user from host 192.168.12.10 to connect to database "template1"
|
# Allow a user from host 192.168.12.10 to connect to database "template1"
|
||||||
# if the user's password in pg_shadow is correctly supplied:
|
# if the user's password is correctly supplied:
|
||||||
#
|
#
|
||||||
# TYPE DATABASE IP_ADDRESS MASK AUTH_TYPE AUTH_ARGUMENT
|
# TYPE DATABASE USER IP_ADDRESS MASK AUTH_TYPE
|
||||||
# host template1 192.168.12.10 255.255.255.255 md5
|
# host template1 all 192.168.12.10 255.255.255.255 md5
|
||||||
#
|
#
|
||||||
# In the absence of preceding "host" lines, these two lines will reject
|
# In the absence of preceding "host" lines, these two lines will reject
|
||||||
# all connection from 192.168.54.1 (since that entry will be matched
|
# all connection from 192.168.54.1 (since that entry will be matched
|
||||||
# first), but allow Kerberos V5 connections from anywhere else on the
|
# first), but allow Kerberos V5 connections from anywhere else on the
|
||||||
# Internet. The zero mask means that no bits of the host IP address are
|
# Internet. The zero mask means that no bits of the host IP address are
|
||||||
# considered, so it matches any host:
|
# considered so it matches any host:
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# TYPE DATABASE IP_ADDRESS MASK AUTH_TYPE AUTH_ARGUMENT
|
# TYPE DATABASE USER IP_ADDRESS MASK AUTH_TYPE
|
||||||
# host all 192.168.54.1 255.255.255.255 reject
|
# host all all 192.168.54.1 255.255.255.255 reject
|
||||||
# host all 0.0.0.0 0.0.0.0 krb5
|
# host all all 0.0.0.0 0.0.0.0 krb5
|
||||||
#
|
#
|
||||||
# Allow users from 192.168.x.x hosts to connect to any database if they
|
# Allow users from 192.168.x.x hosts to connect to any database if they
|
||||||
# pass the ident check. For example, if ident says the user is "james" and
|
# pass the ident check. For example, if ident says the user is "james" and
|
||||||
# he requests to connect as PostgreSQL user "guest", the connection is
|
# he requests to connect as PostgreSQL user "guest", the connection is
|
||||||
# allowed if there is an entry in $PGDATA/pg_ident.conf with map name
|
# allowed if there is an entry in $PGDATA/pg_ident.conf with map name
|
||||||
# "phoenix" that says "james" is allowed to connect as "guest":
|
# "phoenix" that says "james" is allowed to connect as "guest":
|
||||||
#
|
|
||||||
# TYPE DATABASE IP_ADDRESS MASK AUTH_TYPE AUTH_ARGUMENT
|
|
||||||
# host all 192.168.0.0 255.255.0.0 ident phoenix
|
|
||||||
#
|
|
||||||
# If these are the only two lines for local connections, they will allow
|
|
||||||
# local users to connect only to their own databases (databases with the
|
|
||||||
# same name as their user name) except for administrators who may connect
|
|
||||||
# to all databases. The file $PGDATA/admins lists the user names who are
|
|
||||||
# permitted to connect to all databases. Passwords are required in all
|
|
||||||
# cases. (If you prefer to use ident authorization, an ident map can
|
|
||||||
# serve a parallel purpose to the password list file used here.)
|
|
||||||
#
|
|
||||||
# TYPE DATABASE IP_ADDRESS MASK AUTH_TYPE AUTH_ARGUMENT
|
|
||||||
# local sameuser md5
|
|
||||||
# local all md5 admins
|
|
||||||
#
|
|
||||||
# See $PGDATA/pg_ident.conf for more information on Ident maps.
|
# See $PGDATA/pg_ident.conf for more information on Ident maps.
|
||||||
|
#
|
||||||
|
# TYPE DATABASE USER IP_ADDRESS MASK AUTH_TYPE
|
||||||
|
# host all all 192.168.0.0 255.255.0.0 ident phoenix
|
||||||
|
#
|
||||||
|
# If these are the only three lines for local connections, they will
|
||||||
|
# allow local users to connect only to their own databases (databases
|
||||||
|
# with the same name as their user name) except for administrators and
|
||||||
|
# members of group 'support' who may connect to all databases . The file
|
||||||
|
# $PGDATA/admins contains a list of user names. Passwords are required in
|
||||||
|
# all cases.
|
||||||
|
#
|
||||||
|
# TYPE DATABASE USER IP_ADDRESS MASK AUTH_TYPE
|
||||||
|
# local sameuser all md5
|
||||||
|
# local all @admins md5
|
||||||
|
# local all +support md5
|
||||||
|
#
|
||||||
|
# The last two lines above can be combined into a single line:
|
||||||
|
#
|
||||||
|
# local all @admins,+support md5
|
||||||
|
#
|
||||||
|
# The database column can also use lists and file names, but not groups:
|
||||||
|
#
|
||||||
|
# local db1,db2,@demodbs all md5
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@ -250,7 +253,7 @@
|
|||||||
# configuration is probably too liberal for you. Change it to use
|
# configuration is probably too liberal for you. Change it to use
|
||||||
# something other than "trust" authentication.
|
# something other than "trust" authentication.
|
||||||
#
|
#
|
||||||
# TYPE DATABASE IP_ADDRESS MASK AUTH_TYPE AUTH_ARGUMENT
|
# TYPE DATABASE USER IP_ADDRESS MASK AUTH_TYPE
|
||||||
|
|
||||||
local all trust
|
local all all trust
|
||||||
host all 127.0.0.1 255.255.255.255 trust
|
host all all 127.0.0.1 255.255.255.255 trust
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.271 2002/03/15 19:20:35 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.272 2002/04/04 04:25:48 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
*
|
*
|
||||||
@ -748,8 +748,10 @@ PostmasterMain(int argc, char *argv[])
|
|||||||
/*
|
/*
|
||||||
* Load cached files for client authentication.
|
* Load cached files for client authentication.
|
||||||
*/
|
*/
|
||||||
load_hba_and_ident();
|
load_hba();
|
||||||
load_password_cache();
|
load_ident();
|
||||||
|
load_user();
|
||||||
|
load_group();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We're ready to rock and roll...
|
* We're ready to rock and roll...
|
||||||
@ -1389,7 +1391,8 @@ SIGHUP_handler(SIGNAL_ARGS)
|
|||||||
elog(LOG, "Received SIGHUP, reloading configuration files");
|
elog(LOG, "Received SIGHUP, reloading configuration files");
|
||||||
SignalChildren(SIGHUP);
|
SignalChildren(SIGHUP);
|
||||||
ProcessConfigFile(PGC_SIGHUP);
|
ProcessConfigFile(PGC_SIGHUP);
|
||||||
load_hba_and_ident();
|
load_hba();
|
||||||
|
load_ident();
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_SETMASK(&UnBlockSig);
|
PG_SETMASK(&UnBlockSig);
|
||||||
@ -2288,9 +2291,10 @@ sigusr1_handler(SIGNAL_ARGS)
|
|||||||
if (CheckPostmasterSignal(PMSIGNAL_PASSWORD_CHANGE))
|
if (CheckPostmasterSignal(PMSIGNAL_PASSWORD_CHANGE))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Password file has changed.
|
* Password or group file has changed.
|
||||||
*/
|
*/
|
||||||
load_password_cache();
|
load_user();
|
||||||
|
load_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckPostmasterSignal(PMSIGNAL_WAKEN_CHILDREN))
|
if (CheckPostmasterSignal(PMSIGNAL_WAKEN_CHILDREN))
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v 1.6 2001/10/28 06:25:53 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v 1.7 2002/04/04 04:25:49 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -124,8 +124,6 @@ do_quote_ident(text *iptr)
|
|||||||
{
|
{
|
||||||
if (*cp1 == '"')
|
if (*cp1 == '"')
|
||||||
*cp2++ = '"';
|
*cp2++ = '"';
|
||||||
if (*cp1 == '\\')
|
|
||||||
*cp2++ = '\\';
|
|
||||||
*cp2++ = *cp1++;
|
*cp2++ = *cp1++;
|
||||||
}
|
}
|
||||||
*cp2++ = '"';
|
*cp2++ = '"';
|
||||||
@ -234,8 +232,6 @@ do_quote_ident(text *iptr)
|
|||||||
|
|
||||||
if (*cp1 == '"')
|
if (*cp1 == '"')
|
||||||
*cp2++ = '"';
|
*cp2++ = '"';
|
||||||
if (*cp1 == '\\')
|
|
||||||
*cp2++ = '\\';
|
|
||||||
*cp2++ = *cp1++;
|
*cp2++ = *cp1++;
|
||||||
|
|
||||||
len--;
|
len--;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.85 2002/03/04 04:45:27 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.86 2002/04/04 04:25:49 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -236,85 +236,17 @@ pg_convert2(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
#ifdef CYR_RECODE
|
#ifdef CYR_RECODE
|
||||||
|
|
||||||
#define MAX_TOKEN 80
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some standard C libraries, including GNU, have an isblank() function.
|
|
||||||
* Others, including Solaris, do not. So we have our own.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
isblank(const char c)
|
|
||||||
{
|
|
||||||
return c == ' ' || c == '\t';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Grab one token out of fp. Tokens are strings of non-blank
|
|
||||||
* characters bounded by blank characters, beginning of line, and end
|
|
||||||
* of line. Blank means space or tab. Return the token as *buf.
|
|
||||||
* Leave file positioned to character immediately after the token or
|
|
||||||
* EOF, whichever comes first. If no more tokens on line, return null
|
|
||||||
* string as *buf and position file to beginning of next line or EOF,
|
|
||||||
* whichever comes first.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
next_token(FILE *fp, char *buf, const int bufsz)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
char *eb = buf + (bufsz - 1);
|
|
||||||
|
|
||||||
/* Move over initial token-delimiting blanks */
|
|
||||||
while ((c = getc(fp)) != EOF && isblank(c))
|
|
||||||
;
|
|
||||||
|
|
||||||
if (c != EOF && c != '\n')
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* build a token in buf of next characters up to EOF, eol, or
|
|
||||||
* blank. If the token gets too long, we still parse it
|
|
||||||
* correctly, but the excess characters are not stored into *buf.
|
|
||||||
*/
|
|
||||||
while (c != EOF && c != '\n' && !isblank(c))
|
|
||||||
{
|
|
||||||
if (buf < eb)
|
|
||||||
*buf++ = c;
|
|
||||||
c = getc(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Put back the char right after the token (critical in case it is
|
|
||||||
* eol, since we need to detect end-of-line at next call).
|
|
||||||
*/
|
|
||||||
if (c != EOF)
|
|
||||||
ungetc(c, fp);
|
|
||||||
}
|
|
||||||
*buf = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
read_through_eol(FILE *file)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
|
|
||||||
while ((c = getc(file)) != EOF && c != '\n')
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SetCharSet(void)
|
SetCharSet(void)
|
||||||
{
|
{
|
||||||
FILE *file;
|
FILE *file;
|
||||||
char *p;
|
char *filename;
|
||||||
char *map_file;
|
char *map_file;
|
||||||
char buf[MAX_TOKEN];
|
char buf[MAX_TOKEN];
|
||||||
int i,
|
int i,
|
||||||
c;
|
c;
|
||||||
unsigned char FromChar,
|
unsigned char FromChar,
|
||||||
ToChar;
|
ToChar;
|
||||||
char ChTable[80];
|
char ChTable[MAX_TOKEN];
|
||||||
|
|
||||||
for (i = 0; i < 128; i++)
|
for (i = 0; i < 128; i++)
|
||||||
{
|
{
|
||||||
@ -325,39 +257,40 @@ SetCharSet(void)
|
|||||||
if (IsUnderPostmaster)
|
if (IsUnderPostmaster)
|
||||||
{
|
{
|
||||||
GetCharSetByHost(ChTable, MyProcPort->raddr.in.sin_addr.s_addr, DataDir);
|
GetCharSetByHost(ChTable, MyProcPort->raddr.in.sin_addr.s_addr, DataDir);
|
||||||
p = ChTable;
|
filename = ChTable;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
p = getenv("PG_RECODETABLE");
|
filename = getenv("PG_RECODETABLE");
|
||||||
|
|
||||||
if (p && *p != '\0')
|
if (filename && *filename != '\0')
|
||||||
{
|
{
|
||||||
map_file = palloc(strlen(DataDir) + strlen(p) + 2);
|
map_file = palloc(strlen(DataDir) + strlen(filename) + 2);
|
||||||
sprintf(map_file, "%s/%s", DataDir, p);
|
sprintf(map_file, "%s/%s", DataDir, filename);
|
||||||
file = AllocateFile(map_file, PG_BINARY_R);
|
file = AllocateFile(map_file, "r");
|
||||||
pfree(map_file);
|
pfree(map_file);
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
while ((c = getc(file)) != EOF)
|
|
||||||
|
while (!feof(file))
|
||||||
{
|
{
|
||||||
if (c == '#')
|
next_token(file, buf, sizeof(buf));
|
||||||
read_through_eol(file);
|
if (buf[0] != '\0')
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Read the FromChar */
|
FromChar = strtoul(buf, 0, 0);
|
||||||
ungetc(c, file);
|
/* Read the ToChar */
|
||||||
next_token(file, buf, sizeof(buf));
|
next_token(file, buf, sizeof(buf));
|
||||||
if (buf[0] != '\0')
|
if (buf[0] != '\0')
|
||||||
{
|
{
|
||||||
FromChar = strtoul(buf, 0, 0);
|
ToChar = strtoul(buf, 0, 0);
|
||||||
/* Read the ToChar */
|
RecodeForwTable[FromChar - 128] = ToChar;
|
||||||
next_token(file, buf, sizeof(buf));
|
RecodeBackTable[ToChar - 128] = FromChar;
|
||||||
if (buf[0] != '\0')
|
|
||||||
|
/* read to EOL */
|
||||||
|
while (!feof(file) && buf[0])
|
||||||
{
|
{
|
||||||
ToChar = strtoul(buf, 0, 0);
|
next_token(file, buf, sizeof(buf));
|
||||||
RecodeForwTable[FromChar - 128] = ToChar;
|
elog(LOG, "SetCharSet: unknown tag %s in file %s"
|
||||||
RecodeBackTable[ToChar - 128] = FromChar;
|
buf, filename);
|
||||||
read_through_eol(file);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,6 +299,7 @@ SetCharSet(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
convertstr(unsigned char *buff, int len, int dest)
|
convertstr(unsigned char *buff, int len, int dest)
|
||||||
{
|
{
|
||||||
@ -384,7 +318,206 @@ convertstr(unsigned char *buff, int len, int dest)
|
|||||||
}
|
}
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#define CHARSET_FILE "charset.conf"
|
||||||
|
#define MAX_CHARSETS 10
|
||||||
|
#define KEY_HOST 1
|
||||||
|
#define KEY_BASE 2
|
||||||
|
#define KEY_TABLE 3
|
||||||
|
|
||||||
|
struct CharsetItem
|
||||||
|
{
|
||||||
|
char Orig[MAX_TOKEN];
|
||||||
|
char Dest[MAX_TOKEN];
|
||||||
|
char Table[MAX_TOKEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CharSetInRange(char *buf, int host)
|
||||||
|
{
|
||||||
|
int valid,
|
||||||
|
i,
|
||||||
|
FromAddr,
|
||||||
|
ToAddr,
|
||||||
|
tmp;
|
||||||
|
struct in_addr file_ip_addr;
|
||||||
|
char *p;
|
||||||
|
unsigned int one = 0x80000000,
|
||||||
|
NetMask = 0;
|
||||||
|
unsigned char mask;
|
||||||
|
|
||||||
|
p = strchr(buf, '/');
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
*p++ = '\0';
|
||||||
|
valid = inet_aton(buf, &file_ip_addr);
|
||||||
|
if (valid)
|
||||||
|
{
|
||||||
|
mask = strtoul(p, 0, 0);
|
||||||
|
FromAddr = ntohl(file_ip_addr.s_addr);
|
||||||
|
ToAddr = ntohl(file_ip_addr.s_addr);
|
||||||
|
for (i = 0; i < mask; i++)
|
||||||
|
{
|
||||||
|
NetMask |= one;
|
||||||
|
one >>= 1;
|
||||||
|
}
|
||||||
|
FromAddr &= NetMask;
|
||||||
|
ToAddr = ToAddr | ~NetMask;
|
||||||
|
tmp = ntohl(host);
|
||||||
|
return ((unsigned) tmp >= (unsigned) FromAddr &&
|
||||||
|
(unsigned) tmp <= (unsigned) ToAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = strchr(buf, '-');
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
*p++ = '\0';
|
||||||
|
valid = inet_aton(buf, &file_ip_addr);
|
||||||
|
if (valid)
|
||||||
|
{
|
||||||
|
FromAddr = ntohl(file_ip_addr.s_addr);
|
||||||
|
valid = inet_aton(p, &file_ip_addr);
|
||||||
|
if (valid)
|
||||||
|
{
|
||||||
|
ToAddr = ntohl(file_ip_addr.s_addr);
|
||||||
|
tmp = ntohl(host);
|
||||||
|
return ((unsigned) tmp >= (unsigned) FromAddr &&
|
||||||
|
(unsigned) tmp <= (unsigned) ToAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valid = inet_aton(buf, &file_ip_addr);
|
||||||
|
if (valid)
|
||||||
|
{
|
||||||
|
FromAddr = file_ip_addr.s_addr;
|
||||||
|
return (unsigned) FromAddr == (unsigned) host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
GetCharSetByHost(char *TableName, int host, const char *DataDir)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
char buf[MAX_TOKEN],
|
||||||
|
BaseCharset[MAX_TOKEN],
|
||||||
|
OrigCharset[MAX_TOKEN],
|
||||||
|
DestCharset[MAX_TOKEN],
|
||||||
|
HostCharset[MAX_TOKEN],
|
||||||
|
*map_file;
|
||||||
|
int key,
|
||||||
|
ChIndex = 0,
|
||||||
|
c,
|
||||||
|
i,
|
||||||
|
bufsize;
|
||||||
|
struct CharsetItem *ChArray[MAX_CHARSETS];
|
||||||
|
|
||||||
|
*TableName = '\0';
|
||||||
|
bufsize = (strlen(DataDir) + strlen(CHARSET_FILE) + 2) * sizeof(char);
|
||||||
|
map_file = (char *) palloc(bufsize);
|
||||||
|
snprintf(map_file, bufsize, "%s/%s", DataDir, CHARSET_FILE);
|
||||||
|
file = AllocateFile(map_file, "r");
|
||||||
|
pfree(map_file);
|
||||||
|
if (file == NULL)
|
||||||
|
{
|
||||||
|
/* XXX should we log a complaint? */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!feof(file))
|
||||||
|
{
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
key = 0;
|
||||||
|
if (strcasecmp(buf, "HostCharset") == 0)
|
||||||
|
key = KEY_HOST;
|
||||||
|
else if (strcasecmp(buf, "BaseCharset") == 0)
|
||||||
|
key = KEY_BASE;
|
||||||
|
else if (strcasecmp(buf, "RecodeTable") == 0)
|
||||||
|
key = KEY_TABLE;
|
||||||
|
else
|
||||||
|
elog(LOG, "GetCharSetByHost: unknown tag %s in file %s"
|
||||||
|
buf, CHARSET_FILE);
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case KEY_HOST:
|
||||||
|
/* Read the host */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
if (CharSetInRange(buf, host))
|
||||||
|
{
|
||||||
|
/* Read the charset */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
strcpy(HostCharset, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_BASE:
|
||||||
|
/* Read the base charset */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
strcpy(BaseCharset, buf);
|
||||||
|
break;
|
||||||
|
case KEY_TABLE:
|
||||||
|
/* Read the original charset */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
strcpy(OrigCharset, buf);
|
||||||
|
/* Read the destination charset */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
strcpy(DestCharset, buf);
|
||||||
|
/* Read the table filename */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
ChArray[ChIndex] =
|
||||||
|
(struct CharsetItem *) palloc(sizeof(struct CharsetItem));
|
||||||
|
strcpy(ChArray[ChIndex]->Orig, OrigCharset);
|
||||||
|
strcpy(ChArray[ChIndex]->Dest, DestCharset);
|
||||||
|
strcpy(ChArray[ChIndex]->Table, buf);
|
||||||
|
ChIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read to EOL */
|
||||||
|
while (!feof(file) && buf[0])
|
||||||
|
{
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
elog(LOG, "GetCharSetByHost: unknown tag %s in file %s"
|
||||||
|
buf, CHARSET_FILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeFile(file);
|
||||||
|
|
||||||
|
for (i = 0; i < ChIndex; i++)
|
||||||
|
{
|
||||||
|
if (strcasecmp(BaseCharset, ChArray[i]->Orig) == 0 &&
|
||||||
|
strcasecmp(HostCharset, ChArray[i]->Dest) == 0)
|
||||||
|
strncpy(TableName, ChArray[i]->Table, 79);
|
||||||
|
pfree(ChArray[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CYR_RECODE */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
# Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
# Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
# Portions Copyright (c) 1994, Regents of the University of California
|
# Portions Copyright (c) 1994, Regents of the University of California
|
||||||
#
|
#
|
||||||
# $Header: /cvsroot/pgsql/src/bin/Makefile,v 1.34 2001/02/18 18:33:59 momjian Exp $
|
# $Header: /cvsroot/pgsql/src/bin/Makefile,v 1.35 2002/04/04 04:25:50 momjian Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ top_builddir = ../..
|
|||||||
include $(top_builddir)/src/Makefile.global
|
include $(top_builddir)/src/Makefile.global
|
||||||
|
|
||||||
DIRS := initdb initlocation ipcclean pg_ctl pg_dump pg_id \
|
DIRS := initdb initlocation ipcclean pg_ctl pg_dump pg_id \
|
||||||
pg_passwd psql scripts pg_config
|
psql scripts pg_config
|
||||||
|
|
||||||
ifdef MULTIBYTE
|
ifdef MULTIBYTE
|
||||||
DIRS += pg_encoding
|
DIRS += pg_encoding
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
# Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
# Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
# Portions Copyright (c) 1994, Regents of the University of California
|
# Portions Copyright (c) 1994, Regents of the University of California
|
||||||
#
|
#
|
||||||
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.146 2002/04/03 05:39:32 petere Exp $
|
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.147 2002/04/04 04:25:50 momjian Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -603,9 +603,11 @@ $ECHO_N "initializing pg_shadow... "$ECHO_C
|
|||||||
|
|
||||||
"$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <<EOF
|
"$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <<EOF
|
||||||
-- Create a trigger so that direct updates to pg_shadow will be written
|
-- Create a trigger so that direct updates to pg_shadow will be written
|
||||||
-- to the flat password file pg_pwd
|
-- to the flat password/group files pg_pwd and pg_group
|
||||||
CREATE TRIGGER pg_sync_pg_pwd AFTER INSERT OR UPDATE OR DELETE ON pg_shadow \
|
CREATE TRIGGER pg_sync_pg_pwd AFTER INSERT OR UPDATE OR DELETE ON pg_shadow \
|
||||||
FOR EACH ROW EXECUTE PROCEDURE update_pg_pwd();
|
FOR EACH ROW EXECUTE PROCEDURE update_pg_pwd_and_pg_group();
|
||||||
|
CREATE TRIGGER pg_sync_pg_group AFTER INSERT OR UPDATE OR DELETE ON pg_group \
|
||||||
|
FOR EACH ROW EXECUTE PROCEDURE update_pg_pwd_and_pg_group();
|
||||||
-- needs to be done before alter user, because alter user checks that
|
-- needs to be done before alter user, because alter user checks that
|
||||||
-- pg_shadow is secure ...
|
-- pg_shadow is secure ...
|
||||||
REVOKE ALL on pg_shadow FROM public;
|
REVOKE ALL on pg_shadow FROM public;
|
||||||
@ -643,6 +645,11 @@ EOF
|
|||||||
echo "The password file wasn't generated. Please report this problem." 1>&2
|
echo "The password file wasn't generated. Please report this problem." 1>&2
|
||||||
exit_nicely
|
exit_nicely
|
||||||
fi
|
fi
|
||||||
|
if [ ! -f "$PGDATA"/global/pg_group ]; then
|
||||||
|
echo
|
||||||
|
echo "The group file wasn't generated. Please report this problem." 1>&2
|
||||||
|
exit_nicely
|
||||||
|
fi
|
||||||
echo "ok"
|
echo "ok"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
# $Header: /cvsroot/pgsql/src/bin/pg_passwd/Attic/Makefile,v 1.14 2001/05/12 19:49:47 petere Exp $
|
|
||||||
|
|
||||||
subdir = src/bin/pg_passwd
|
|
||||||
top_builddir = ../../..
|
|
||||||
include $(top_builddir)/src/Makefile.global
|
|
||||||
|
|
||||||
OBJS = pg_passwd.o
|
|
||||||
ifdef STRDUP
|
|
||||||
OBJS += $(top_builddir)/src/utils/strdup.o
|
|
||||||
endif
|
|
||||||
|
|
||||||
all: pg_passwd
|
|
||||||
|
|
||||||
pg_passwd: $(OBJS)
|
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@
|
|
||||||
|
|
||||||
$(top_builddir)/src/utils/strdup.o:
|
|
||||||
$(MAKE) -C $(top_builddir)/src/utils strdup.o
|
|
||||||
|
|
||||||
install: all installdirs
|
|
||||||
$(INSTALL_PROGRAM) pg_passwd$(X) $(DESTDIR)$(bindir)/pg_passwd$(X)
|
|
||||||
|
|
||||||
installdirs:
|
|
||||||
$(mkinstalldirs) $(DESTDIR)$(bindir)
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -f $(DESTDIR)$(bindir)/pg_passwd$(X)
|
|
||||||
|
|
||||||
depend dep:
|
|
||||||
$(CC) -MM $(CFLAGS) *.c >depend
|
|
||||||
|
|
||||||
clean distclean maintainer-clean:
|
|
||||||
rm -f pg_passwd$(X) pg_passwd.o
|
|
||||||
|
|
||||||
ifeq (depend,$(wildcard depend))
|
|
||||||
include depend
|
|
||||||
endif
|
|
@ -1,412 +0,0 @@
|
|||||||
/*
|
|
||||||
* @(#) pg_passwd.c 1.8 09:13:16 97/07/02 Y. Ichikawa
|
|
||||||
*/
|
|
||||||
#include "postgres_fe.h"
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#define issaltchar(c) (isalnum((unsigned char) (c)) || (c) == '.' || (c) == '/')
|
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS_H
|
|
||||||
#include <termios.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_CRYPT_H
|
|
||||||
#include <crypt.h>
|
|
||||||
#else
|
|
||||||
extern char *crypt(const char *, const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We assume that the output of crypt(3) is always 13 characters,
|
|
||||||
* and that at most 8 characters can usefully be sent to it.
|
|
||||||
*
|
|
||||||
* Postgres usernames are assumed to be less than NAMEDATALEN chars long.
|
|
||||||
*/
|
|
||||||
#define CLEAR_PASSWD_LEN 8 /* not including null */
|
|
||||||
#define CRYPTED_PASSWD_LEN 13 /* not including null */
|
|
||||||
|
|
||||||
const char *progname;
|
|
||||||
|
|
||||||
static void usage(void);
|
|
||||||
static void read_pwd_file(char *filename);
|
|
||||||
static void write_pwd_file(char *filename, char *bkname);
|
|
||||||
static void encrypt_pwd(char key[CLEAR_PASSWD_LEN + 1],
|
|
||||||
char salt[3],
|
|
||||||
char passwd[CRYPTED_PASSWD_LEN + 1]);
|
|
||||||
static void prompt_for_username(char *username);
|
|
||||||
static void prompt_for_password(char *prompt, char *password);
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
printf("%s manipulates flat text password files for PostgreSQL.\n\n", progname);
|
|
||||||
printf("Usage:\n %s PASSWORD-FILE\n\n", progname);
|
|
||||||
printf("Report bugs to <pgsql-bugs@postgresql.org>.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *uname;
|
|
||||||
char *pwd;
|
|
||||||
char *rest;
|
|
||||||
} pg_pwd;
|
|
||||||
|
|
||||||
#define MAXPWDS 1024
|
|
||||||
|
|
||||||
pg_pwd pwds[MAXPWDS];
|
|
||||||
int npwds = 0;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
read_pwd_file(char *filename)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
static char line[512];
|
|
||||||
static char ans[128];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
try_again:
|
|
||||||
fp = fopen(filename, PG_BINARY_R);
|
|
||||||
if (fp == NULL)
|
|
||||||
{
|
|
||||||
if (errno == ENOENT)
|
|
||||||
{
|
|
||||||
printf("File \"%s\" does not exist. Create? (y/n): ", filename);
|
|
||||||
fflush(stdout);
|
|
||||||
if (fgets(ans, sizeof(ans), stdin) == NULL)
|
|
||||||
exit(1);
|
|
||||||
switch (ans[0])
|
|
||||||
{
|
|
||||||
case 'y':
|
|
||||||
case 'Y':
|
|
||||||
fp = fopen(filename, PG_BINARY_W);
|
|
||||||
if (fp == NULL)
|
|
||||||
{
|
|
||||||
perror(filename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
goto try_again;
|
|
||||||
default:
|
|
||||||
/* cannot continue */
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
perror(filename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read all the entries */
|
|
||||||
for (npwds = 0;
|
|
||||||
npwds < MAXPWDS && fgets(line, sizeof(line), fp) != NULL;
|
|
||||||
++npwds)
|
|
||||||
{
|
|
||||||
int l;
|
|
||||||
char *p,
|
|
||||||
*q;
|
|
||||||
|
|
||||||
l = strlen(line);
|
|
||||||
if (line[l - 1] == '\n')
|
|
||||||
line[l - 1] = '\0';
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s:%d: line too long\n",
|
|
||||||
filename, npwds + 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get user name */
|
|
||||||
p = line;
|
|
||||||
if ((q = strchr(p, ':')) != NULL)
|
|
||||||
*q = '\0';
|
|
||||||
|
|
||||||
if (strlen(p) == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s:%d: null user name\n",
|
|
||||||
filename, npwds + 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
pwds[npwds].uname = strdup(p);
|
|
||||||
|
|
||||||
/* check for duplicate user name */
|
|
||||||
for (i = 0; i < npwds; ++i)
|
|
||||||
{
|
|
||||||
if (strcmp(pwds[i].uname, pwds[npwds].uname) == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Duplicate username %s in entry %d\n",
|
|
||||||
pwds[npwds].uname, npwds + 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get password field */
|
|
||||||
if (q)
|
|
||||||
{
|
|
||||||
p = q + 1;
|
|
||||||
q = strchr(p, ':');
|
|
||||||
|
|
||||||
if (q != NULL)
|
|
||||||
*(q++) = '\0';
|
|
||||||
|
|
||||||
if (strlen(p) != CRYPTED_PASSWD_LEN && strcmp(p, "+") != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s:%d: warning: invalid password length\n",
|
|
||||||
filename, npwds + 1);
|
|
||||||
}
|
|
||||||
pwds[npwds].pwd = strdup(p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pwds[npwds].pwd = NULL;
|
|
||||||
|
|
||||||
/* rest of the line is treated as is */
|
|
||||||
if (q == NULL)
|
|
||||||
pwds[npwds].rest = NULL;
|
|
||||||
else
|
|
||||||
pwds[npwds].rest = strdup(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_pwd_file(char *filename, char *bkname)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* make the backup file */
|
|
||||||
link_again:
|
|
||||||
if (link(filename, bkname))
|
|
||||||
{
|
|
||||||
if (errno == EEXIST)
|
|
||||||
{
|
|
||||||
unlink(bkname);
|
|
||||||
goto link_again;
|
|
||||||
}
|
|
||||||
perror(bkname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (unlink(filename))
|
|
||||||
{
|
|
||||||
perror(filename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* open file */
|
|
||||||
if ((fp = fopen(filename, PG_BINARY_W)) == NULL)
|
|
||||||
{
|
|
||||||
perror(filename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write file */
|
|
||||||
for (i = 0; i < npwds; ++i)
|
|
||||||
{
|
|
||||||
fprintf(fp, "%s", pwds[i].uname);
|
|
||||||
if (pwds[i].pwd)
|
|
||||||
fprintf(fp, ":%s", pwds[i].pwd);
|
|
||||||
if (pwds[i].rest)
|
|
||||||
fprintf(fp, ":%s", pwds[i].rest);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
encrypt_pwd(char key[CLEAR_PASSWD_LEN + 1],
|
|
||||||
char salt[3],
|
|
||||||
char passwd[CRYPTED_PASSWD_LEN + 1])
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
/* select a salt, if not already given */
|
|
||||||
if (salt[0] == '\0')
|
|
||||||
{
|
|
||||||
srand(time(NULL));
|
|
||||||
do
|
|
||||||
{
|
|
||||||
n = rand() % 256;
|
|
||||||
} while (!issaltchar(n));
|
|
||||||
salt[0] = n;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
n = rand() % 256;
|
|
||||||
} while (!issaltchar(n));
|
|
||||||
salt[1] = n;
|
|
||||||
salt[2] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get encrypted password */
|
|
||||||
strcpy(passwd, crypt(key, salt));
|
|
||||||
|
|
||||||
#ifdef PG_PASSWD_DEBUG
|
|
||||||
/* show it */
|
|
||||||
fprintf(stderr, "key = %s, salt = %s, password = %s\n",
|
|
||||||
key, salt, passwd);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
prompt_for_username(char *username)
|
|
||||||
{
|
|
||||||
int length;
|
|
||||||
|
|
||||||
printf("Username: ");
|
|
||||||
fflush(stdout);
|
|
||||||
if (fgets(username, NAMEDATALEN, stdin) == NULL)
|
|
||||||
username[0] = '\0';
|
|
||||||
|
|
||||||
length = strlen(username);
|
|
||||||
if (length > 0 && username[length - 1] != '\n')
|
|
||||||
{
|
|
||||||
/* eat rest of the line */
|
|
||||||
char buf[128];
|
|
||||||
int buflen;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (fgets(buf, sizeof(buf), stdin) == NULL)
|
|
||||||
break;
|
|
||||||
buflen = strlen(buf);
|
|
||||||
} while (buflen > 0 && buf[buflen - 1] != '\n');
|
|
||||||
}
|
|
||||||
if (length > 0 && username[length - 1] == '\n')
|
|
||||||
username[length - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
prompt_for_password(char *prompt, char *password)
|
|
||||||
{
|
|
||||||
int length;
|
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS_H
|
|
||||||
struct termios t_orig,
|
|
||||||
t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS_H
|
|
||||||
tcgetattr(0, &t);
|
|
||||||
t_orig = t;
|
|
||||||
t.c_lflag &= ~ECHO;
|
|
||||||
tcsetattr(0, TCSADRAIN, &t);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printf(prompt);
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
if (fgets(password, CLEAR_PASSWD_LEN + 1, stdin) == NULL)
|
|
||||||
password[0] = '\0';
|
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS_H
|
|
||||||
tcsetattr(0, TCSADRAIN, &t_orig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
length = strlen(password);
|
|
||||||
if (length > 0 && password[length - 1] != '\n')
|
|
||||||
{
|
|
||||||
/* eat rest of the line */
|
|
||||||
char buf[128];
|
|
||||||
int buflen;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (fgets(buf, sizeof(buf), stdin) == NULL)
|
|
||||||
break;
|
|
||||||
buflen = strlen(buf);
|
|
||||||
} while (buflen > 0 && buf[buflen - 1] != '\n');
|
|
||||||
}
|
|
||||||
if (length > 0 && password[length - 1] == '\n')
|
|
||||||
password[length - 1] = '\0';
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
char bkname[MAXPGPATH];
|
|
||||||
char username[NAMEDATALEN];
|
|
||||||
char salt[3];
|
|
||||||
char key[CLEAR_PASSWD_LEN + 1],
|
|
||||||
key2[CLEAR_PASSWD_LEN + 1];
|
|
||||||
char e_passwd[CRYPTED_PASSWD_LEN + 1];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
progname = argv[0];
|
|
||||||
|
|
||||||
if (argc != 2)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s: too %s arguments\nTry '%s --help' for more information.\n",
|
|
||||||
progname, argc > 2 ? "many" : "few", progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
|
|
||||||
{
|
|
||||||
usage();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
|
|
||||||
{
|
|
||||||
puts("pg_passwd (PostgreSQL) " PG_VERSION);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
if (argv[1][0] == '-')
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s: invalid option: %s\nTry '%s --help' for more information.\n",
|
|
||||||
progname, argv[1], progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = argv[1];
|
|
||||||
|
|
||||||
/* open file */
|
|
||||||
read_pwd_file(filename);
|
|
||||||
|
|
||||||
/* ask for the user name and the password */
|
|
||||||
prompt_for_username(username);
|
|
||||||
prompt_for_password("New password: ", key);
|
|
||||||
prompt_for_password("Re-enter new password: ", key2);
|
|
||||||
if (strcmp(key, key2) != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Password mismatch\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
salt[0] = '\0';
|
|
||||||
encrypt_pwd(key, salt, e_passwd);
|
|
||||||
|
|
||||||
/* check password entry */
|
|
||||||
for (i = 0; i < npwds; ++i)
|
|
||||||
{
|
|
||||||
if (strcmp(pwds[i].uname, username) == 0)
|
|
||||||
{ /* found */
|
|
||||||
pwds[i].pwd = strdup(e_passwd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == npwds)
|
|
||||||
{ /* did not exist */
|
|
||||||
if (npwds == MAXPWDS)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Cannot handle so many entries\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
pwds[npwds].uname = strdup(username);
|
|
||||||
pwds[npwds].pwd = strdup(e_passwd);
|
|
||||||
pwds[npwds].rest = NULL;
|
|
||||||
++npwds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write back the file */
|
|
||||||
sprintf(bkname, "%s.bk", filename);
|
|
||||||
write_pwd_file(filename, bkname);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: pg_proc.h,v 1.224 2002/03/29 19:06:19 tgl Exp $
|
* $Id: pg_proc.h,v 1.225 2002/04/04 04:25:52 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* The script catalog/genbki.sh reads this file and generates .bki
|
* The script catalog/genbki.sh reads this file and generates .bki
|
||||||
@ -2101,8 +2101,8 @@ DESCR("does not match LIKE expression, case-insensitive");
|
|||||||
DATA(insert OID = 1637 ( like_escape PGUID 12 f t t t 2 f 25 "25 25" 100 0 0 100 like_escape - _null_ ));
|
DATA(insert OID = 1637 ( like_escape PGUID 12 f t t t 2 f 25 "25 25" 100 0 0 100 like_escape - _null_ ));
|
||||||
DESCR("convert match pattern to use backslash escapes");
|
DESCR("convert match pattern to use backslash escapes");
|
||||||
|
|
||||||
DATA(insert OID = 1689 ( update_pg_pwd PGUID 12 f t f t 0 f 0 "" 100 0 0 100 update_pg_pwd - _null_ ));
|
DATA(insert OID = 1689 ( update_pg_pwd_and_pg_group PGUID 12 f t f t 0 f 0 "" 100 0 0 100 update_pg_pwd_and_pg_group - _null_ ));
|
||||||
DESCR("update pg_pwd file");
|
DESCR("update pg_pwd and pg_group files");
|
||||||
|
|
||||||
/* Oracle Compatibility Related Functions - By Edmund Mergl <E.Mergl@bawue.de> */
|
/* Oracle Compatibility Related Functions - By Edmund Mergl <E.Mergl@bawue.de> */
|
||||||
DATA(insert OID = 868 ( strpos PGUID 12 f t t t 2 f 23 "25 25" 100 0 0 100 textpos - _null_ ));
|
DATA(insert OID = 868 ( strpos PGUID 12 f t t t 2 f 23 "25 25" 100 0 0 100 textpos - _null_ ));
|
||||||
|
@ -3,15 +3,23 @@
|
|||||||
* user.h
|
* user.h
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* $Id: user.h,v 1.17 2002/03/01 22:45:17 petere Exp $
|
* $Id: user.h,v 1.18 2002/04/04 04:25:53 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#ifndef USER_H
|
#ifndef USER_H
|
||||||
#define USER_H
|
#define USER_H
|
||||||
|
|
||||||
|
#include "fmgr.h"
|
||||||
#include "nodes/parsenodes.h"
|
#include "nodes/parsenodes.h"
|
||||||
|
|
||||||
|
#define PWD_FILE "pg_pwd"
|
||||||
|
|
||||||
|
#define USER_GROUP_FILE "pg_group"
|
||||||
|
|
||||||
|
|
||||||
|
extern char *group_getfilename(void);
|
||||||
|
extern char *user_getfilename(void);
|
||||||
extern void CreateUser(CreateUserStmt *stmt);
|
extern void CreateUser(CreateUserStmt *stmt);
|
||||||
extern void AlterUser(AlterUserStmt *stmt);
|
extern void AlterUser(AlterUserStmt *stmt);
|
||||||
extern void AlterUserSet(AlterUserSetStmt *stmt);
|
extern void AlterUserSet(AlterUserSetStmt *stmt);
|
||||||
@ -21,6 +29,6 @@ extern void CreateGroup(CreateGroupStmt *stmt);
|
|||||||
extern void AlterGroup(AlterGroupStmt *stmt, const char *tag);
|
extern void AlterGroup(AlterGroupStmt *stmt, const char *tag);
|
||||||
extern void DropGroup(DropGroupStmt *stmt);
|
extern void DropGroup(DropGroupStmt *stmt);
|
||||||
|
|
||||||
extern Datum update_pg_pwd(PG_FUNCTION_ARGS);
|
extern Datum update_pg_pwd_and_pg_group(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
#endif /* USER_H */
|
#endif /* USER_H */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: crypt.h,v 1.19 2001/11/12 01:52:46 momjian Exp $
|
* $Id: crypt.h,v 1.20 2002/04/04 04:25:53 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
#include "libpq/libpq-be.h"
|
#include "libpq/libpq-be.h"
|
||||||
|
|
||||||
#define CRYPT_PWD_FILE_SEPSTR "\t"
|
|
||||||
|
|
||||||
/* Also defined in interfaces/odbc/md5.h */
|
/* Also defined in interfaces/odbc/md5.h */
|
||||||
#define MD5_PASSWD_LEN 35
|
#define MD5_PASSWD_LEN 35
|
||||||
|
|
||||||
@ -24,9 +22,6 @@
|
|||||||
strlen(passwd) == MD5_PASSWD_LEN)
|
strlen(passwd) == MD5_PASSWD_LEN)
|
||||||
|
|
||||||
|
|
||||||
extern char *crypt_getpwdfilename(void);
|
|
||||||
extern void load_password_cache(void);
|
|
||||||
|
|
||||||
extern int md5_crypt_verify(const Port *port, const char *user,
|
extern int md5_crypt_verify(const Port *port, const char *user,
|
||||||
const char *pgpass);
|
const char *pgpass);
|
||||||
extern bool md5_hash(const void *buff, size_t len, char *hexsum);
|
extern bool md5_hash(const void *buff, size_t len, char *hexsum);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Interface to hba.c
|
* Interface to hba.c
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* $Id: hba.h,v 1.31 2001/11/05 17:46:33 momjian Exp $
|
* $Id: hba.h,v 1.32 2002/04/04 04:25:54 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -15,15 +15,14 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "nodes/pg_list.h"
|
||||||
|
|
||||||
#define CONF_FILE "pg_hba.conf"
|
#define CONF_FILE "pg_hba.conf"
|
||||||
/* Name of the config file */
|
/* Name of the config file */
|
||||||
|
|
||||||
#define USERMAP_FILE "pg_ident.conf"
|
#define USERMAP_FILE "pg_ident.conf"
|
||||||
/* Name of the usermap file */
|
/* Name of the usermap file */
|
||||||
|
|
||||||
#define OLD_CONF_FILE "pg_hba"
|
|
||||||
/* Name of the config file in prior releases of Postgres. */
|
|
||||||
|
|
||||||
#define IDENT_PORT 113
|
#define IDENT_PORT 113
|
||||||
/* Standard TCP port number for Ident service. Assigned by IANA */
|
/* Standard TCP port number for Ident service. Assigned by IANA */
|
||||||
|
|
||||||
@ -46,8 +45,15 @@ typedef enum UserAuth
|
|||||||
|
|
||||||
typedef struct Port hbaPort;
|
typedef struct Port hbaPort;
|
||||||
|
|
||||||
|
#define MAX_TOKEN 256
|
||||||
|
|
||||||
|
extern void next_token(FILE *fp, char *buf, const int bufsz);
|
||||||
|
extern List **get_user_line(const char *user);
|
||||||
|
extern void load_hba(void);
|
||||||
|
extern void load_ident(void);
|
||||||
|
extern void load_user(void);
|
||||||
|
extern void load_group(void);
|
||||||
extern int hba_getauthmethod(hbaPort *port);
|
extern int hba_getauthmethod(hbaPort *port);
|
||||||
extern int authident(hbaPort *port);
|
extern int authident(hbaPort *port);
|
||||||
extern void load_hba_and_ident(void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: miscadmin.h,v 1.101 2002/03/04 01:46:04 tgl Exp $
|
* $Id: miscadmin.h,v 1.102 2002/04/04 04:25:51 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* some of the information in this file should be moved to
|
* some of the information in this file should be moved to
|
||||||
@ -219,7 +219,6 @@ extern int FindExec(char *full_path, const char *argv0,
|
|||||||
extern int CheckPathAccess(char *path, char *name, int open_mode);
|
extern int CheckPathAccess(char *path, char *name, int open_mode);
|
||||||
|
|
||||||
#ifdef CYR_RECODE
|
#ifdef CYR_RECODE
|
||||||
extern void GetCharSetByHost(char *TableName, int host, const char *DataDir);
|
|
||||||
extern void SetCharSet(void);
|
extern void SetCharSet(void);
|
||||||
extern char *convertstr(unsigned char *buff, int len, int dest);
|
extern char *convertstr(unsigned char *buff, int len, int dest);
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,7 +30,7 @@ WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR
|
|||||||
AND p1.proname !~ '^pl[^_]+_call_handler$'
|
AND p1.proname !~ '^pl[^_]+_call_handler$'
|
||||||
AND p1.proname !~ '^RI_FKey_'
|
AND p1.proname !~ '^RI_FKey_'
|
||||||
AND p1.proname !~ 'costestimate$'
|
AND p1.proname !~ 'costestimate$'
|
||||||
AND p1.proname != 'update_pg_pwd';
|
AND p1.proname != 'update_pg_pwd_and_pg_group';
|
||||||
oid | proname
|
oid | proname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
@ -33,7 +33,7 @@ WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR
|
|||||||
AND p1.proname !~ '^pl[^_]+_call_handler$'
|
AND p1.proname !~ '^pl[^_]+_call_handler$'
|
||||||
AND p1.proname !~ '^RI_FKey_'
|
AND p1.proname !~ '^RI_FKey_'
|
||||||
AND p1.proname !~ 'costestimate$'
|
AND p1.proname !~ 'costestimate$'
|
||||||
AND p1.proname != 'update_pg_pwd';
|
AND p1.proname != 'update_pg_pwd_and_pg_group';
|
||||||
|
|
||||||
-- Look for conflicting proc definitions (same names and input datatypes).
|
-- Look for conflicting proc definitions (same names and input datatypes).
|
||||||
-- (This test should be dead code now that we have the unique index
|
-- (This test should be dead code now that we have the unique index
|
||||||
|
Loading…
x
Reference in New Issue
Block a user