]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/openpam/bin/pamtest/pamtest.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / openpam / bin / pamtest / pamtest.c
1 /*-
2  * Copyright (c) 2011 Dag-Erling Smørgrav
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote
15  *    products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $Id: pamtest.c 595 2012-04-14 14:28:35Z des $
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <err.h>
38 #include <pwd.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44
45 #include <security/pam_appl.h>
46 #include <security/openpam.h>   /* for openpam_ttyconv() */
47
48 /* OpenPAM internals */
49 extern const char *pam_item_name[PAM_NUM_ITEMS];
50 extern int openpam_debug;
51
52 static pam_handle_t *pamh;
53 static struct pam_conv pamc;
54
55 static int silent;
56 static int verbose;
57
58 static void pt_verbose(const char *, ...)
59         OPENPAM_FORMAT ((__printf__, 1, 2));
60 static void pt_error(int, const char *, ...)
61         OPENPAM_FORMAT ((__printf__, 2, 3));
62
63 /*
64  * Print an information message if -v was specified at least once
65  */
66 static void
67 pt_verbose(const char *fmt, ...)
68 {
69         va_list ap;
70
71         if (verbose) {
72                 va_start(ap, fmt);
73                 vfprintf(stderr, fmt, ap);
74                 va_end(ap);
75                 fprintf(stderr, "\n");
76         }
77 }
78
79 /*
80  * Print an error message
81  */
82 static void
83 pt_error(int e, const char *fmt, ...)
84 {
85         va_list ap;
86
87         if (e == PAM_SUCCESS && !verbose)
88                 return;
89         va_start(ap, fmt);
90         vfprintf(stderr, fmt, ap);
91         va_end(ap);
92         fprintf(stderr, ": %s\n", pam_strerror(NULL, e));
93 }
94
95 /*
96  * Wrapper for pam_start(3)
97  */
98 static int
99 pt_start(const char *service, const char *user)
100 {
101         int pame;
102
103         pamc.conv = &openpam_ttyconv;
104         pt_verbose("pam_start(%s, %s)", service, user);
105         if ((pame = pam_start(service, user, &pamc, &pamh)) != PAM_SUCCESS)
106                 pt_error(pame, "pam_start(%s)", service);
107         return (pame);
108 }
109
110 /*
111  * Wrapper for pam_authenticate(3)
112  */
113 static int
114 pt_authenticate(int flags)
115 {
116         int pame;
117
118         flags |= silent;
119         if ((pame = pam_authenticate(pamh, flags)) != PAM_SUCCESS)
120                 pt_error(pame, "pam_authenticate()");
121         return (pame);
122 }
123
124 /*
125  * Wrapper for pam_acct_mgmt(3)
126  */
127 static int
128 pt_acct_mgmt(int flags)
129 {
130         int pame;
131
132         flags |= silent;
133         if ((pame = pam_acct_mgmt(pamh, flags)) != PAM_SUCCESS)
134                 pt_error(pame, "pam_acct_mgmt()");
135         return (pame);
136 }
137
138 /*
139  * Wrapper for pam_chauthtok(3)
140  */
141 static int
142 pt_chauthtok(int flags)
143 {
144         int pame;
145
146         flags |= silent;
147         if ((pame = pam_chauthtok(pamh, flags)) != PAM_SUCCESS)
148                 pt_error(pame, "pam_chauthtok()");
149         return (pame);
150 }
151
152 /*
153  * Wrapper for pam_setcred(3)
154  */
155 static int
156 pt_setcred(int flags)
157 {
158         int pame;
159
160         flags |= silent;
161         if ((pame = pam_setcred(pamh, flags)) != PAM_SUCCESS)
162                 pt_error(pame, "pam_setcred()");
163         return (pame);
164 }
165
166 /*
167  * Wrapper for pam_open_session(3)
168  */
169 static int
170 pt_open_session(int flags)
171 {
172         int pame;
173
174         flags |= silent;
175         if ((pame = pam_open_session(pamh, flags)) != PAM_SUCCESS)
176                 pt_error(pame, "pam_open_session()");
177         return (pame);
178 }
179
180 /*
181  * Wrapper for pam_close_session(3)
182  */
183 static int
184 pt_close_session(int flags)
185 {
186         int pame;
187
188         flags |= silent;
189         if ((pame = pam_close_session(pamh, flags)) != PAM_SUCCESS)
190                 pt_error(pame, "pam_close_session()");
191         return (pame);
192 }
193
194 /*
195  * Wrapper for pam_set_item(3)
196  */
197 static int
198 pt_set_item(int item, const char *p)
199 {
200         int pame;
201
202         switch (item) {
203         case PAM_SERVICE:
204         case PAM_USER:
205         case PAM_AUTHTOK:
206         case PAM_OLDAUTHTOK:
207         case PAM_TTY:
208         case PAM_RHOST:
209         case PAM_RUSER:
210         case PAM_USER_PROMPT:
211         case PAM_AUTHTOK_PROMPT:
212         case PAM_OLDAUTHTOK_PROMPT:
213         case PAM_HOST:
214                 pt_verbose("setting %s to %s", pam_item_name[item], p);
215                 break;
216         default:
217                 pt_verbose("setting %s", pam_item_name[item]);
218                 break;
219         }
220         if ((pame = pam_set_item(pamh, item, p)) != PAM_SUCCESS)
221                 pt_error(pame, "pam_set_item(%s)", pam_item_name[item]);
222         return (pame);
223 }
224
225 /*
226  * Wrapper for pam_end(3)
227  */
228 static int
229 pt_end(int pame)
230 {
231
232         if (pamh != NULL && (pame = pam_end(pamh, pame)) != PAM_SUCCESS)
233                 /* can't happen */
234                 pt_error(pame, "pam_end()");
235         return (pame);
236 }
237
238 /*
239  * Retrieve and list the PAM environment variables
240  */
241 static int
242 pt_listenv(void)
243 {
244         char **pam_envlist, **pam_env;
245
246         if ((pam_envlist = pam_getenvlist(pamh)) == NULL ||
247             *pam_envlist == NULL) {
248                 pt_verbose("no environment variables.");
249         } else {
250                 pt_verbose("environment variables:");
251                 for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) {
252                         printf(" %s\n", *pam_env);
253                         free(*pam_env);
254                 }
255         }
256         free(pam_envlist);
257         return (PAM_SUCCESS);
258 }
259
260 /*
261  * Print usage string and exit
262  */
263 static void
264 usage(void)
265 {
266
267         fprintf(stderr, "usage: pamtest %s service command ...\n",
268             "[-dkMPsv] [-H rhost] [-h host] [-t tty] [-U ruser] [-u user]");
269         exit(1);
270 }
271
272 /*
273  * Handle an option that takes a string argument and can be used only once
274  */
275 static void
276 opt_str_once(int opt, const char **p, const char *arg)
277 {
278
279         if (*p != NULL) {
280                 fprintf(stderr, "The -%c option can only be used once\n", opt);
281                 usage();
282         }
283         *p = arg;
284 }
285
286 /*
287  * Entry point
288  */
289 int
290 main(int argc, char *argv[])
291 {
292         char hostname[1024];
293         const char *rhost = NULL;
294         const char *host = NULL;
295         const char *ruser = NULL;
296         const char *user = NULL;
297         const char *service = NULL;
298         const char *tty = NULL;
299         int keepatit = 0;
300         int pame;
301         int opt;
302
303         while ((opt = getopt(argc, argv, "dH:h:kMPst:U:u:v")) != -1)
304                 switch (opt) {
305                 case 'd':
306                         openpam_debug++;
307                         break;
308                 case 'H':
309                         opt_str_once(opt, &rhost, optarg);
310                         break;
311                 case 'h':
312                         opt_str_once(opt, &host, optarg);
313                         break;
314                 case 'k':
315                         keepatit = 1;
316                         break;
317                 case 'M':
318                         openpam_set_feature(OPENPAM_RESTRICT_MODULE_NAME, 0);
319                         openpam_set_feature(OPENPAM_VERIFY_MODULE_FILE, 0);
320                         break;
321                 case 'P':
322                         openpam_set_feature(OPENPAM_RESTRICT_SERVICE_NAME, 0);
323                         openpam_set_feature(OPENPAM_VERIFY_POLICY_FILE, 0);
324                         break;
325                 case 's':
326                         silent = PAM_SILENT;
327                         break;
328                 case 't':
329                         opt_str_once(opt, &tty, optarg);
330                         break;
331                 case 'U':
332                         opt_str_once(opt, &ruser, optarg);
333                         break;
334                 case 'u':
335                         opt_str_once(opt, &user, optarg);
336                         break;
337                 case 'v':
338                         verbose++;
339                         break;
340                 default:
341                         usage();
342                 }
343
344         argc -= optind;
345         argv += optind;
346
347         if (argc < 1)
348                 usage();
349
350         service = *argv;
351         --argc;
352         ++argv;
353
354         /* defaults */
355         if (rhost == NULL) {
356                 if (gethostname(hostname, sizeof(hostname)) == -1)
357                         err(1, "gethostname()");
358                 rhost = hostname;
359         }
360         if (tty == NULL)
361                 tty = ttyname(STDERR_FILENO);
362         if (user == NULL)
363                 user = getlogin();
364         if (ruser == NULL)
365                 ruser = user;
366
367         /* initialize PAM */
368         if ((pame = pt_start(service, user)) != PAM_SUCCESS)
369                 goto end;
370
371         /*
372          * pam_start(3) sets this to the machine's hostname, but we allow
373          * the user to override it.
374          */
375         if (host != NULL)
376                 if ((pame = pt_set_item(PAM_HOST, host)) != PAM_SUCCESS)
377                     goto end;
378
379         /*
380          * The remote host / user / tty are usually set by the
381          * application.
382          */
383         if ((pame = pt_set_item(PAM_RHOST, rhost)) != PAM_SUCCESS ||
384             (pame = pt_set_item(PAM_RUSER, ruser)) != PAM_SUCCESS ||
385             (pame = pt_set_item(PAM_TTY, tty)) != PAM_SUCCESS)
386                 goto end;
387
388         while (argc > 0) {
389                 if (strcmp(*argv, "listenv") == 0 ||
390                     strcmp(*argv, "env") == 0) {
391                         pame = pt_listenv();
392                 } else if (strcmp(*argv, "authenticate") == 0 ||
393                     strcmp(*argv, "auth") == 0) {
394                         pame = pt_authenticate(0);
395                 } else if (strcmp(*argv, "acct_mgmt") == 0 ||
396                     strcmp(*argv, "account") == 0) {
397                         pame = pt_acct_mgmt(0);
398                 } else if (strcmp(*argv, "chauthtok") == 0 ||
399                     strcmp(*argv, "change") == 0) {
400                         pame = pt_chauthtok(PAM_CHANGE_EXPIRED_AUTHTOK);
401                 } else if (strcmp(*argv, "forcechauthtok") == 0 ||
402                     strcmp(*argv, "forcechange") == 0) {
403                         pame = pt_chauthtok(0);
404                 } else if (strcmp(*argv, "setcred") == 0 ||
405                     strcmp(*argv, "establish_cred") == 0) {
406                         pame = pt_setcred(PAM_ESTABLISH_CRED);
407                 } else if (strcmp(*argv, "open_session") == 0 ||
408                     strcmp(*argv, "open") == 0) {
409                         pame = pt_open_session(0);
410                 } else if (strcmp(*argv, "close_session") == 0 ||
411                     strcmp(*argv, "close") == 0) {
412                         pame = pt_close_session(0);
413                 } else if (strcmp(*argv, "unsetcred") == 0 ||
414                     strcmp(*argv, "delete_cred") == 0) {
415                         pame = pt_setcred(PAM_DELETE_CRED);
416                 } else {
417                         warnx("unknown primitive: %s", *argv);
418                         pame = PAM_SYSTEM_ERR;
419                 }
420                 if (pame != PAM_SUCCESS && !keepatit) {
421                         warnx("test aborted");
422                         break;
423                 }
424                 --argc;
425                 ++argv;
426         }
427
428 end:
429         (void)pt_end(pame);
430         exit(pame == PAM_SUCCESS ? 0 : 1);
431 }