1 /* This file is part of pam-modules.
2    Copyright (C) 2006-2008, 2010-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 <graypam.h>
18 
19 
20 /* Command line parsing */
21 static long debug_level;
22 
23 static int xargc;
24 static const char **xargv;
25 static int priority = LOG_INFO;
26 static int facility = LOG_AUTHPRIV;
27 static const char *syslog_tag = MODULE_NAME;
28 static int do_open = 1;
29 
30 static struct keyword syslog_facility[] = {
31         DCL("user",       LOG_USER),
32 	DCL("daemon",     LOG_DAEMON),
33 	DCL("auth",       LOG_AUTH),
34 	DCL("authpriv",   LOG_AUTHPRIV),
35 	DCL("local0",     LOG_LOCAL0),
36 	DCL("local1",     LOG_LOCAL1),
37 	DCL("local2",     LOG_LOCAL2),
38 	DCL("local3",     LOG_LOCAL3),
39 	DCL("local4",     LOG_LOCAL4),
40 	DCL("local5",     LOG_LOCAL5),
41 	DCL("local6",     LOG_LOCAL6),
42 	DCL("local7",     LOG_LOCAL7),
43 	{ NULL }
44 };
45 
46 static struct keyword syslog_priority[] = {
47         DCL("emerg",      LOG_EMERG ),
48 	DCL("alert",      LOG_ALERT ),
49 	DCL("crit",       LOG_CRIT ),
50 	DCL("err",        LOG_ERR ),
51 	DCL("warning",    LOG_WARNING ),
52 	DCL("notice",     LOG_NOTICE ),
53 	DCL("info",       LOG_INFO ),
54 	DCL("debug",      LOG_DEBUG ),
55 	{ NULL }
56 };
57 
58 static int
parse_priority(struct pam_opt * opt,const char * str)59 parse_priority(struct pam_opt *opt, const char *str)
60 {
61 	int len;
62 	struct keyword *kw;
63 
64 	for (len = 0; str[len]; len++)
65 		if (ispunct(str[len]))
66 			break;
67 
68 	if (len) {
69 		kw = gray_find_keyword(syslog_facility, str, len);
70 		if (!kw) {
71 			_pam_log(LOG_ERR,
72 				 "unknown syslog facility: %*.*s",
73 				 len, len, str);
74 			return 1;
75 		}
76 		facility = kw->code;
77 	}
78 
79 	if (str[len]) {
80 		str += len + 1;
81 		kw = gray_find_keyword(syslog_priority, str, strlen(str));
82 		if (!kw) {
83 			_pam_log(LOG_ERR,
84 				 "unknown syslog priority: %s", str);
85 			return 1;
86 		}
87 		priority = kw->code;
88 	}
89 	return 0;
90 }
91 
92 struct pam_opt pam_opt[] = {
93 	{ PAM_OPTSTR(debug), pam_opt_long, &debug_level },
94 	{ PAM_OPTSTR(debug), pam_opt_const, &debug_level, { 1 } },
95 	{ PAM_OPTSTR(audit), pam_opt_const, &debug_level, { 100 } },
96 	{ PAM_OPTSTR(waitdebug), pam_opt_null, NULL, { 0 },
97 	  gray_wait_debug_fun },
98 	{ PAM_OPTSTR(tag), pam_opt_string, &syslog_tag },
99 	{ PAM_OPTSTR(pri), pam_opt_null, NULL, { 0 }, parse_priority },
100 	{ PAM_OPTSTR(open), pam_opt_bool, &do_open },
101 	{ NULL }
102 };
103 
104 
105 static void
_pam_parse(pam_handle_t * pamh,int argc,const char ** argv)106 _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
107 {
108 	int i;
109 	const char **targv;
110 
111 	gray_log_init(0, MODULE_NAME, LOG_AUTHPRIV);
112 
113 	targv = gray_malloc(argc * sizeof (targv[0]));
114 	for (i = 0; i < argc; i++) {
115 		if (argv[i][0] == '-') {
116 			if (argv[i][1] == '-' && argv[i][2] == 0)
117 				break;
118 			targv[i] = argv[i] + 1;
119 		} else
120 			break;
121 	}
122 
123 	gray_parseopt(pam_opt, i, targv);
124 	free(targv);
125 
126 	xargc = argc - i;
127 	xargv = argv + i;
128 
129 	closelog();
130 	gray_log_init(!do_open, syslog_tag, facility);
131 }
132 
133 static int
echo(pam_handle_t * pamh,const char * prefix,int argc,const char ** argv)134 echo(pam_handle_t *pamh, const char *prefix, int argc, const char **argv)
135 {
136 	char *str;
137 	gray_slist_t slist;
138 
139 	_pam_parse(pamh, argc, argv);
140 	slist = gray_slist_create();
141 	if (prefix) {
142 		gray_slist_append(slist, prefix, strlen(prefix));
143 		gray_slist_append(slist, ": ", 2);
144 	}
145 	gray_expand_argv(pamh, xargc, xargv, slist);
146 	gray_slist_append_char(slist, 0);
147 	str = gray_slist_finish(slist);
148 	_pam_log(priority, "%s", str);
149 	gray_slist_free(&slist);
150 	return PAM_IGNORE;
151 }
152 
153 
154 
155 PAM_EXTERN int
pam_sm_authenticate(pam_handle_t * pamh,int flags,int argc,const char ** argv)156 pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
157 {
158 	gray_pam_init(PAM_IGNORE);
159 	return echo(pamh, __FUNCTION__, argc, argv);
160 }
161 
162 PAM_EXTERN int
pam_sm_setcred(pam_handle_t * pamh,int flags,int argc,const char ** argv)163 pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
164 {
165 	gray_pam_init(PAM_IGNORE);
166 	return echo(pamh, __FUNCTION__, argc, argv);
167 }
168 
169 PAM_EXTERN int
pam_sm_chauthtok(pam_handle_t * pamh,int flags,int argc,const char ** argv)170 pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv)
171 {
172 	gray_pam_init(PAM_IGNORE);
173 	return echo(pamh, __FUNCTION__, argc, argv);
174 }
175 
176 PAM_EXTERN int
pam_sm_acct_mgmt(pam_handle_t * pamh,int flags,int argc,const char ** argv)177 pam_sm_acct_mgmt (pam_handle_t *pamh, int flags, int argc, const char **argv)
178 {
179 	gray_pam_init(PAM_IGNORE);
180 	return echo(pamh, __FUNCTION__, argc, argv);
181 }
182 
183 PAM_EXTERN int
pam_sm_open_session(pam_handle_t * pamh,int flags,int argc,const char ** argv)184 pam_sm_open_session (pam_handle_t *pamh, int flags, int argc,
185                      const char **argv)
186 {
187 	gray_pam_init(PAM_IGNORE);
188 	return echo(pamh, __FUNCTION__, argc, argv);
189 }
190 
191 PAM_EXTERN int
pam_sm_close_session(pam_handle_t * pamh,int flags,int argc,const char ** argv)192 pam_sm_close_session (pam_handle_t *pamh, int flags, int argc,
193 		      const char **argv)
194 {
195 	gray_pam_init(PAM_IGNORE);
196 	return echo(pamh, __FUNCTION__, argc, argv);
197 }
198 
199 #ifdef PAM_STATIC
200 
201 /* static module data */
202 
203 struct pam_module _pam_log_modstruct = {
204     "pam_log",
205     pam_sm_authenticate,
206     pam_sm_setcred,
207     pam_sm_acct_mgmt,
208     pam_sm_open_session,
209     pam_sm_close_session,
210     pam_sm_chauthtok,
211 };
212 
213 #endif
214 
215 /* end of module definition */
216