YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

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