1 /* This file is part of pam-modules.
2    Copyright (C) 2009-2012, 2014-2015, 2018 Sergey Poznyakoff
3 
4    This program is free software; you can redistribute it and/or modify it
5    under the terms of the GNU General Public License as published by the
6    Free Software Foundation; either version 3 of the License, or (at your
7    option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License along
15    with this program.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include "pamck.h"
18 char *program_name;
19 
20 void
usage()21 usage()
22 {
23 	printf("usage: %s [-hv] [-s service] [-g group] user [password]\n",
24 	       program_name);
25 }
26 
27 void
help()28 help()
29 {
30 	printf("usage: %s [-hv] [-s service] [-g group] user [password]\n",
31 	       program_name);
32 	printf("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
33 	printf("%s home page: <http://www.gnu.org.ua/software/%s/>.\n",
34 	       PACKAGE_NAME, PACKAGE);
35 }
36 
37 void
version()38 version()
39 {
40 	printf("%s (%s) %s\n", program_name, PACKAGE, PACKAGE_VERSION);
41 	fputs ("\
42 Copyright (C) 2009-2015 Sergey Poznyakoff\n\
43 \n\
44 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n\
45 This is free software: you are free to change and redistribute it.\n\
46 There is NO WARRANTY, to the extent permitted by law.\n\
47 \n\
48 ", stdout);
49 }
50 
51 void
error(int code,const char * fmt,...)52 error(int code, const char *fmt, ...)
53 {
54 	va_list ap;
55 	va_start(ap, fmt);
56 	fprintf(stderr, "%s: ", program_name);
57 	vfprintf(stderr, fmt, ap);
58 	fputc('\n', stderr);
59 	va_end(ap);
60 	if (code)
61 		exit(code);
62 }
63 
64 
65 struct grouptab {
66 	char *name;
67 	char *funcname;
68 	int (*pam_fn) (pam_handle_t *pamh, int flags);
69 } grouptab[] = {
70 	{ "auth", "pam_authenticate", pam_authenticate },
71 	{ "acct", "pam_acct_mgmt", pam_acct_mgmt },
72 	{ "open", "pam_open_session", pam_open_session },
73 	{ "close", "pam_close_session", pam_close_session },
74 	{ "pass", "pam_chauthtok", pam_chauthtok },
75 	{ NULL }
76 };
77 
78 struct grouptab *
find_group(char * name)79 find_group(char *name)
80 {
81 	struct grouptab *p;
82 	for (p = grouptab; p->name; p++)
83 		if (strcmp(p->name, name) == 0)
84 			return p;
85 	return NULL;
86 }
87 
88 void
groupprint()89 groupprint()
90 {
91 	struct grouptab *p;
92 	for (p = grouptab; p->name; p++)
93 		printf("%s\n", p->name);
94 }
95 
96 char *service = "check";
97 struct grouptab *group;
98 char *user;
99 char *pass;
100 
101 static struct pam_conv conv = {
102     pamck_conv,
103     NULL
104 };
105 
106 void
check_default(pam_handle_t * pamh)107 check_default(pam_handle_t *pamh)
108 {
109 	int rc;
110 
111         rc = pam_authenticate(pamh, 0);
112 	if (rc)
113 		error(2, "%s failed: %s",
114 		      "pam_authenticate", pam_strerror (pamh, rc));
115 	rc = pam_acct_mgmt(pamh, 0);
116 	if (rc)
117 		error(2, "%s failed: %s",
118 		      "pam_acct_mgmt", pam_strerror (pamh, rc));
119 	printf("OK\n");
120 }
121 
122 void
check_group(pam_handle_t * pamh,struct grouptab * grp)123 check_group(pam_handle_t *pamh, struct grouptab *grp)
124 {
125 	int rc = grp->pam_fn(pamh, 0);
126 	if (rc)
127 		error(2, "%s failed: %s", grp->funcname,
128 		      pam_strerror (pamh, rc));
129 }
130 
131 int
main(int argc,char ** argv)132 main (int argc, char **argv)
133 {
134 	int c;
135 	int rc;
136 	pam_handle_t *pamh = NULL;
137 
138 	program_name = argv[0];
139 	/* A bit of sugar to fake common GNU-style long options */
140 	if (argc == 2) {
141 		if (strcmp (argv[1], "--help") == 0) {
142 			help();
143 			exit(0);
144 		} if (strcmp (argv[1], "--usage") == 0) {
145 			usage();
146 			exit(0);
147 		} else if (strcmp (argv[1], "--version") == 0) {
148 			version();
149 			exit(0);
150 		}
151 	}
152 	/* Normal option processing */
153 	while ((c = getopt (argc, argv, "hg:s:v")) != EOF) {
154 		switch (c) {
155 		case 'h':
156 			help();
157 			exit(0);
158 
159 		case 'g':
160 			if (strcmp(optarg, "help") == 0) {
161 				groupprint();
162 				exit(0);
163 			}
164 			group = find_group(optarg);
165 			if (!group)
166 				error(1,
167 				      "no such management group, try `%s -g help' for the list",
168 				      program_name);
169 
170 			break;
171 
172 		case 's':
173 			service = optarg;
174 			break;
175 
176 		case 'v':
177 			version();
178 			exit(0);
179 
180 		default:
181 			exit(1);
182 		}
183 	}
184 
185 	argc -= optind;
186 	argv += optind;
187 
188 	switch (argc) {
189 	case 2:
190 		pass = argv[1];
191 	case 1:
192 		user = argv[0];
193 		break;
194 	default:
195 		usage();
196 		exit(1);
197 	}
198 
199 	rc = pam_start(service, user, &conv, &pamh);
200 	if (rc)
201 		error(2, "pam_start failed");
202 
203 	if (group)
204 		check_group(pamh, group);
205 	else
206 		check_default(pamh);
207 
208 	if (pam_end(pamh, rc) != PAM_SUCCESS) {
209 		pamh = NULL;
210 		error(2, "failed to release authenticator");
211 	}
212 
213 	exit (0);
214 }
215