LCOV - code coverage report
Current view: top level - src/bin/scripts - createuser.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 124 197 62.9 %
Date: 2019-06-19 14:06:47 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * createuser
       4             :  *
       5             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       6             :  * Portions Copyright (c) 1994, Regents of the University of California
       7             :  *
       8             :  * src/bin/scripts/createuser.c
       9             :  *
      10             :  *-------------------------------------------------------------------------
      11             :  */
      12             : 
      13             : #include "postgres_fe.h"
      14             : #include "common.h"
      15             : #include "common/logging.h"
      16             : #include "fe_utils/simple_list.h"
      17             : #include "fe_utils/string_utils.h"
      18             : 
      19             : 
      20             : static void help(const char *progname);
      21             : 
      22             : int
      23          30 : main(int argc, char *argv[])
      24             : {
      25             :     static struct option long_options[] = {
      26             :         {"host", required_argument, NULL, 'h'},
      27             :         {"port", required_argument, NULL, 'p'},
      28             :         {"username", required_argument, NULL, 'U'},
      29             :         {"role", required_argument, NULL, 'g'},
      30             :         {"no-password", no_argument, NULL, 'w'},
      31             :         {"password", no_argument, NULL, 'W'},
      32             :         {"echo", no_argument, NULL, 'e'},
      33             :         {"createdb", no_argument, NULL, 'd'},
      34             :         {"no-createdb", no_argument, NULL, 'D'},
      35             :         {"superuser", no_argument, NULL, 's'},
      36             :         {"no-superuser", no_argument, NULL, 'S'},
      37             :         {"createrole", no_argument, NULL, 'r'},
      38             :         {"no-createrole", no_argument, NULL, 'R'},
      39             :         {"inherit", no_argument, NULL, 'i'},
      40             :         {"no-inherit", no_argument, NULL, 'I'},
      41             :         {"login", no_argument, NULL, 'l'},
      42             :         {"no-login", no_argument, NULL, 'L'},
      43             :         {"replication", no_argument, NULL, 1},
      44             :         {"no-replication", no_argument, NULL, 2},
      45             :         {"interactive", no_argument, NULL, 3},
      46             :         /* adduser is obsolete, undocumented spelling of superuser */
      47             :         {"adduser", no_argument, NULL, 'a'},
      48             :         {"no-adduser", no_argument, NULL, 'A'},
      49             :         {"connection-limit", required_argument, NULL, 'c'},
      50             :         {"pwprompt", no_argument, NULL, 'P'},
      51             :         {"encrypted", no_argument, NULL, 'E'},
      52             :         {NULL, 0, NULL, 0}
      53             :     };
      54             : 
      55             :     const char *progname;
      56             :     int         optindex;
      57             :     int         c;
      58          30 :     const char *newuser = NULL;
      59          30 :     char       *host = NULL;
      60          30 :     char       *port = NULL;
      61          30 :     char       *username = NULL;
      62          30 :     SimpleStringList roles = {NULL, NULL};
      63          30 :     enum trivalue prompt_password = TRI_DEFAULT;
      64          30 :     bool        echo = false;
      65          30 :     bool        interactive = false;
      66          30 :     char       *conn_limit = NULL;
      67          30 :     bool        pwprompt = false;
      68          30 :     char       *newpassword = NULL;
      69             :     char        newuser_buf[128];
      70             :     char        newpassword_buf[100];
      71             : 
      72             :     /* Tri-valued variables.  */
      73          30 :     enum trivalue createdb = TRI_DEFAULT,
      74          30 :                 superuser = TRI_DEFAULT,
      75          30 :                 createrole = TRI_DEFAULT,
      76          30 :                 inherit = TRI_DEFAULT,
      77          30 :                 login = TRI_DEFAULT,
      78          30 :                 replication = TRI_DEFAULT;
      79             : 
      80             :     PQExpBufferData sql;
      81             : 
      82             :     PGconn     *conn;
      83             :     PGresult   *result;
      84             : 
      85          30 :     pg_logging_init(argv[0]);
      86          30 :     progname = get_progname(argv[0]);
      87          30 :     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
      88             : 
      89          30 :     handle_help_version_opts(argc, argv, "createuser", help);
      90             : 
      91          26 :     while ((c = getopt_long(argc, argv, "h:p:U:g:wWedDsSaArRiIlLc:PE",
      92             :                             long_options, &optindex)) != -1)
      93             :     {
      94          26 :         switch (c)
      95             :         {
      96             :             case 'h':
      97           0 :                 host = pg_strdup(optarg);
      98           0 :                 break;
      99             :             case 'p':
     100           0 :                 port = pg_strdup(optarg);
     101           0 :                 break;
     102             :             case 'U':
     103           4 :                 username = pg_strdup(optarg);
     104           4 :                 break;
     105             :             case 'g':
     106           0 :                 simple_string_list_append(&roles, optarg);
     107           0 :                 break;
     108             :             case 'w':
     109           0 :                 prompt_password = TRI_NO;
     110           0 :                 break;
     111             :             case 'W':
     112           0 :                 prompt_password = TRI_YES;
     113           0 :                 break;
     114             :             case 'e':
     115           0 :                 echo = true;
     116           0 :                 break;
     117             :             case 'd':
     118           0 :                 createdb = TRI_YES;
     119           0 :                 break;
     120             :             case 'D':
     121           0 :                 createdb = TRI_NO;
     122           0 :                 break;
     123             :             case 's':
     124             :             case 'a':
     125          16 :                 superuser = TRI_YES;
     126          16 :                 break;
     127             :             case 'S':
     128             :             case 'A':
     129           0 :                 superuser = TRI_NO;
     130           0 :                 break;
     131             :             case 'r':
     132           2 :                 createrole = TRI_YES;
     133           2 :                 break;
     134             :             case 'R':
     135           0 :                 createrole = TRI_NO;
     136           0 :                 break;
     137             :             case 'i':
     138           0 :                 inherit = TRI_YES;
     139           0 :                 break;
     140             :             case 'I':
     141           0 :                 inherit = TRI_NO;
     142           0 :                 break;
     143             :             case 'l':
     144           0 :                 login = TRI_YES;
     145           0 :                 break;
     146             :             case 'L':
     147           2 :                 login = TRI_NO;
     148           2 :                 break;
     149             :             case 'c':
     150           0 :                 conn_limit = pg_strdup(optarg);
     151           0 :                 break;
     152             :             case 'P':
     153           0 :                 pwprompt = true;
     154           0 :                 break;
     155             :             case 'E':
     156             :                 /* no-op, accepted for backward compatibility */
     157           0 :                 break;
     158             :             case 1:
     159           0 :                 replication = TRI_YES;
     160           0 :                 break;
     161             :             case 2:
     162           0 :                 replication = TRI_NO;
     163           0 :                 break;
     164             :             case 3:
     165           0 :                 interactive = true;
     166           0 :                 break;
     167             :             default:
     168           2 :                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
     169           2 :                 exit(1);
     170             :         }
     171             :     }
     172             : 
     173          24 :     switch (argc - optind)
     174             :     {
     175             :         case 0:
     176           0 :             break;
     177             :         case 1:
     178          24 :             newuser = argv[optind];
     179          24 :             break;
     180             :         default:
     181           0 :             pg_log_error("too many command-line arguments (first is \"%s\")",
     182             :                          argv[optind + 1]);
     183           0 :             fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
     184           0 :             exit(1);
     185             :     }
     186             : 
     187          24 :     if (newuser == NULL)
     188             :     {
     189           0 :         if (interactive)
     190             :         {
     191           0 :             simple_prompt("Enter name of role to add: ",
     192             :                           newuser_buf, sizeof(newuser_buf), true);
     193           0 :             newuser = newuser_buf;
     194             :         }
     195             :         else
     196             :         {
     197           0 :             if (getenv("PGUSER"))
     198           0 :                 newuser = getenv("PGUSER");
     199             :             else
     200           0 :                 newuser = get_user_name_or_exit(progname);
     201             :         }
     202             :     }
     203             : 
     204          24 :     if (pwprompt)
     205             :     {
     206             :         char        pw2[100];
     207             : 
     208           0 :         simple_prompt("Enter password for new role: ",
     209             :                       newpassword_buf, sizeof(newpassword_buf), false);
     210           0 :         simple_prompt("Enter it again: ", pw2, sizeof(pw2), false);
     211           0 :         if (strcmp(newpassword_buf, pw2) != 0)
     212             :         {
     213           0 :             fprintf(stderr, _("Passwords didn't match.\n"));
     214           0 :             exit(1);
     215             :         }
     216           0 :         newpassword = newpassword_buf;
     217             :     }
     218             : 
     219          24 :     if (superuser == 0)
     220             :     {
     221           8 :         if (interactive && yesno_prompt("Shall the new role be a superuser?"))
     222           0 :             superuser = TRI_YES;
     223             :         else
     224           8 :             superuser = TRI_NO;
     225             :     }
     226             : 
     227          24 :     if (superuser == TRI_YES)
     228             :     {
     229             :         /* Not much point in trying to restrict a superuser */
     230          16 :         createdb = TRI_YES;
     231          16 :         createrole = TRI_YES;
     232             :     }
     233             : 
     234          24 :     if (createdb == 0)
     235             :     {
     236           8 :         if (interactive && yesno_prompt("Shall the new role be allowed to create databases?"))
     237           0 :             createdb = TRI_YES;
     238             :         else
     239           8 :             createdb = TRI_NO;
     240             :     }
     241             : 
     242          24 :     if (createrole == 0)
     243             :     {
     244           6 :         if (interactive && yesno_prompt("Shall the new role be allowed to create more new roles?"))
     245           0 :             createrole = TRI_YES;
     246             :         else
     247           6 :             createrole = TRI_NO;
     248             :     }
     249             : 
     250          24 :     if (inherit == 0)
     251          24 :         inherit = TRI_YES;
     252             : 
     253          24 :     if (login == 0)
     254          22 :         login = TRI_YES;
     255             : 
     256          24 :     conn = connectDatabase("postgres", host, port, username, prompt_password,
     257             :                            progname, echo, false, false);
     258             : 
     259          24 :     initPQExpBuffer(&sql);
     260             : 
     261          24 :     printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser));
     262          24 :     if (newpassword)
     263             :     {
     264             :         char       *encrypted_password;
     265             : 
     266           0 :         appendPQExpBufferStr(&sql, " PASSWORD ");
     267             : 
     268           0 :         encrypted_password = PQencryptPasswordConn(conn,
     269             :                                                    newpassword,
     270             :                                                    newuser,
     271             :                                                    NULL);
     272           0 :         if (!encrypted_password)
     273             :         {
     274           0 :             pg_log_error("password encryption failed: %s",
     275             :                          PQerrorMessage(conn));
     276           0 :             exit(1);
     277             :         }
     278           0 :         appendStringLiteralConn(&sql, encrypted_password, conn);
     279           0 :         PQfreemem(encrypted_password);
     280             :     }
     281          24 :     if (superuser == TRI_YES)
     282          16 :         appendPQExpBufferStr(&sql, " SUPERUSER");
     283          24 :     if (superuser == TRI_NO)
     284           8 :         appendPQExpBufferStr(&sql, " NOSUPERUSER");
     285          24 :     if (createdb == TRI_YES)
     286          16 :         appendPQExpBufferStr(&sql, " CREATEDB");
     287          24 :     if (createdb == TRI_NO)
     288           8 :         appendPQExpBufferStr(&sql, " NOCREATEDB");
     289          24 :     if (createrole == TRI_YES)
     290          18 :         appendPQExpBufferStr(&sql, " CREATEROLE");
     291          24 :     if (createrole == TRI_NO)
     292           6 :         appendPQExpBufferStr(&sql, " NOCREATEROLE");
     293          24 :     if (inherit == TRI_YES)
     294          24 :         appendPQExpBufferStr(&sql, " INHERIT");
     295          24 :     if (inherit == TRI_NO)
     296           0 :         appendPQExpBufferStr(&sql, " NOINHERIT");
     297          24 :     if (login == TRI_YES)
     298          22 :         appendPQExpBufferStr(&sql, " LOGIN");
     299          24 :     if (login == TRI_NO)
     300           2 :         appendPQExpBufferStr(&sql, " NOLOGIN");
     301          24 :     if (replication == TRI_YES)
     302           0 :         appendPQExpBufferStr(&sql, " REPLICATION");
     303          24 :     if (replication == TRI_NO)
     304           0 :         appendPQExpBufferStr(&sql, " NOREPLICATION");
     305          24 :     if (conn_limit != NULL)
     306           0 :         appendPQExpBuffer(&sql, " CONNECTION LIMIT %s", conn_limit);
     307          24 :     if (roles.head != NULL)
     308             :     {
     309             :         SimpleStringListCell *cell;
     310             : 
     311           0 :         appendPQExpBufferStr(&sql, " IN ROLE ");
     312             : 
     313           0 :         for (cell = roles.head; cell; cell = cell->next)
     314             :         {
     315           0 :             if (cell->next)
     316           0 :                 appendPQExpBuffer(&sql, "%s,", fmtId(cell->val));
     317             :             else
     318           0 :                 appendPQExpBufferStr(&sql, fmtId(cell->val));
     319             :         }
     320             :     }
     321          24 :     appendPQExpBufferChar(&sql, ';');
     322             : 
     323          24 :     if (echo)
     324           0 :         printf("%s\n", sql.data);
     325          24 :     result = PQexec(conn, sql.data);
     326             : 
     327          24 :     if (PQresultStatus(result) != PGRES_COMMAND_OK)
     328             :     {
     329           2 :         pg_log_error("creation of new role failed: %s", PQerrorMessage(conn));
     330           2 :         PQfinish(conn);
     331           2 :         exit(1);
     332             :     }
     333             : 
     334          22 :     PQclear(result);
     335          22 :     PQfinish(conn);
     336          22 :     exit(0);
     337             : }
     338             : 
     339             : 
     340             : static void
     341           2 : help(const char *progname)
     342             : {
     343           2 :     printf(_("%s creates a new PostgreSQL role.\n\n"), progname);
     344           2 :     printf(_("Usage:\n"));
     345           2 :     printf(_("  %s [OPTION]... [ROLENAME]\n"), progname);
     346           2 :     printf(_("\nOptions:\n"));
     347           2 :     printf(_("  -c, --connection-limit=N  connection limit for role (default: no limit)\n"));
     348           2 :     printf(_("  -d, --createdb            role can create new databases\n"));
     349           2 :     printf(_("  -D, --no-createdb         role cannot create databases (default)\n"));
     350           2 :     printf(_("  -e, --echo                show the commands being sent to the server\n"));
     351           2 :     printf(_("  -g, --role=ROLE           new role will be a member of this role\n"));
     352           2 :     printf(_("  -i, --inherit             role inherits privileges of roles it is a\n"
     353             :              "                            member of (default)\n"));
     354           2 :     printf(_("  -I, --no-inherit          role does not inherit privileges\n"));
     355           2 :     printf(_("  -l, --login               role can login (default)\n"));
     356           2 :     printf(_("  -L, --no-login            role cannot login\n"));
     357           2 :     printf(_("  -P, --pwprompt            assign a password to new role\n"));
     358           2 :     printf(_("  -r, --createrole          role can create new roles\n"));
     359           2 :     printf(_("  -R, --no-createrole       role cannot create roles (default)\n"));
     360           2 :     printf(_("  -s, --superuser           role will be superuser\n"));
     361           2 :     printf(_("  -S, --no-superuser        role will not be superuser (default)\n"));
     362           2 :     printf(_("  -V, --version             output version information, then exit\n"));
     363           2 :     printf(_("  --interactive             prompt for missing role name and attributes rather\n"
     364             :              "                            than using defaults\n"));
     365           2 :     printf(_("  --replication             role can initiate replication\n"));
     366           2 :     printf(_("  --no-replication          role cannot initiate replication\n"));
     367           2 :     printf(_("  -?, --help                show this help, then exit\n"));
     368           2 :     printf(_("\nConnection options:\n"));
     369           2 :     printf(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));
     370           2 :     printf(_("  -p, --port=PORT           database server port\n"));
     371           2 :     printf(_("  -U, --username=USERNAME   user name to connect as (not the one to create)\n"));
     372           2 :     printf(_("  -w, --no-password         never prompt for password\n"));
     373           2 :     printf(_("  -W, --password            force password prompt\n"));
     374           2 :     printf(_("\nReport bugs to <pgsql-bugs@lists.postgresql.org>.\n"));
     375           2 : }

Generated by: LCOV version 1.13