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