1/*-
2 * Copyright (c) 2002-2003 Networks Associates Technology, Inc.
3 * Copyright (c) 2004-2015 Dag-Erling Sm��rgrav
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by ThinkSec AS and
7 * Network Associates Laboratories, the Security Research Division of
8 * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
9 * ("CBOSS"), as part of the DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote
20 *    products derived from this software without specific prior written
21 *    permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#ifndef SECURITY_OPENPAM_H_INCLUDED
37#define SECURITY_OPENPAM_H_INCLUDED
38
39/*
40 * Annoying but necessary header pollution
41 */
42#include <stdarg.h>
43
44#include <security/openpam_attr.h>
45
46#ifdef __cplusplus
47extern "C" {
48#endif
49
50struct passwd;
51
52/*
53 * API extensions
54 */
55int
56openpam_borrow_cred(pam_handle_t *_pamh,
57	const struct passwd *_pwd)
58	OPENPAM_NONNULL((1,2));
59
60int
61openpam_subst(const pam_handle_t *_pamh,
62	char *_buf,
63	size_t *_bufsize,
64	const char *_template);
65
66void
67openpam_free_data(pam_handle_t *_pamh,
68	void *_data,
69	int _status);
70
71void
72openpam_free_envlist(char **_envlist);
73
74const char *
75openpam_get_option(pam_handle_t *_pamh,
76	const char *_option);
77
78int
79openpam_restore_cred(pam_handle_t *_pamh)
80	OPENPAM_NONNULL((1));
81
82int
83openpam_set_option(pam_handle_t *_pamh,
84	const char *_option,
85	const char *_value);
86
87int
88pam_error(const pam_handle_t *_pamh,
89	const char *_fmt,
90	...)
91	OPENPAM_FORMAT ((__printf__, 2, 3))
92	OPENPAM_NONNULL((1,2));
93
94int
95pam_get_authtok(pam_handle_t *_pamh,
96	int _item,
97	const char **_authtok,
98	const char *_prompt)
99	OPENPAM_NONNULL((1,3));
100
101int
102pam_info(const pam_handle_t *_pamh,
103	const char *_fmt,
104	...)
105	OPENPAM_FORMAT ((__printf__, 2, 3))
106	OPENPAM_NONNULL((1,2));
107
108int
109pam_prompt(const pam_handle_t *_pamh,
110	int _style,
111	char **_resp,
112	const char *_fmt,
113	...)
114	OPENPAM_FORMAT ((__printf__, 4, 5))
115	OPENPAM_NONNULL((1,4));
116
117int
118pam_setenv(pam_handle_t *_pamh,
119	const char *_name,
120	const char *_value,
121	int _overwrite)
122	OPENPAM_NONNULL((1,2,3));
123
124int
125pam_vinfo(const pam_handle_t *_pamh,
126	const char *_fmt,
127	va_list _ap)
128	OPENPAM_FORMAT ((__printf__, 2, 0))
129	OPENPAM_NONNULL((1,2));
130
131int
132pam_verror(const pam_handle_t *_pamh,
133	const char *_fmt,
134	va_list _ap)
135	OPENPAM_FORMAT ((__printf__, 2, 0))
136	OPENPAM_NONNULL((1,2));
137
138int
139pam_vprompt(const pam_handle_t *_pamh,
140	int _style,
141	char **_resp,
142	const char *_fmt,
143	va_list _ap)
144	OPENPAM_FORMAT ((__printf__, 4, 0))
145	OPENPAM_NONNULL((1,4));
146
147/*
148 * Read cooked lines.
149 * Checking for _IOFBF is a fairly reliable way to detect the presence
150 * of <stdio.h>, as SUSv3 requires it to be defined there.
151 */
152#ifdef _IOFBF
153char *
154openpam_readline(FILE *_f,
155	int *_lineno,
156	size_t *_lenp)
157	OPENPAM_NONNULL((1));
158
159char **
160openpam_readlinev(FILE *_f,
161	int *_lineno,
162	int *_lenp)
163	OPENPAM_NONNULL((1));
164
165char *
166openpam_readword(FILE *_f,
167	int *_lineno,
168	size_t *_lenp)
169	OPENPAM_NONNULL((1));
170#endif
171
172int
173openpam_straddch(char **_str,
174	size_t *_sizep,
175	size_t *_lenp,
176	int ch)
177	OPENPAM_NONNULL((1));
178
179/*
180 * Enable / disable optional features
181 */
182enum {
183	OPENPAM_RESTRICT_SERVICE_NAME,
184	OPENPAM_VERIFY_POLICY_FILE,
185	OPENPAM_RESTRICT_MODULE_NAME,
186	OPENPAM_VERIFY_MODULE_FILE,
187	OPENPAM_FALLBACK_TO_OTHER,
188	OPENPAM_NUM_FEATURES
189};
190
191int
192openpam_set_feature(int _feature, int _onoff);
193
194int
195openpam_get_feature(int _feature, int *_onoff);
196
197/*
198 * Log levels
199 */
200enum {
201	PAM_LOG_LIBDEBUG = -1,
202	PAM_LOG_DEBUG,
203	PAM_LOG_VERBOSE,
204	PAM_LOG_NOTICE,
205	PAM_LOG_ERROR
206};
207
208/*
209 * Log to syslog
210 */
211void
212_openpam_log(int _level,
213	const char *_func,
214	const char *_fmt,
215	...)
216	OPENPAM_FORMAT ((__printf__, 3, 4))
217	OPENPAM_NONNULL((3));
218
219#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
220#define openpam_log(lvl, ...) \
221	_openpam_log((lvl), __func__, __VA_ARGS__)
222#elif defined(__GNUC__) && (__GNUC__ >= 3)
223#define openpam_log(lvl, ...) \
224	_openpam_log((lvl), __func__, __VA_ARGS__)
225#elif defined(__GNUC__) && (__GNUC__ >= 2) && (__GNUC_MINOR__ >= 95)
226#define openpam_log(lvl, fmt...) \
227	_openpam_log((lvl), __func__, ##fmt)
228#elif defined(__GNUC__) && defined(__FUNCTION__)
229#define openpam_log(lvl, fmt...) \
230	_openpam_log((lvl), __FUNCTION__, ##fmt)
231#else
232void
233openpam_log(int _level,
234	const char *_format,
235	...)
236	OPENPAM_FORMAT ((__printf__, 2, 3))
237	OPENPAM_NONNULL((2));
238#endif
239
240/*
241 * Generic conversation function
242 */
243struct pam_message;
244struct pam_response;
245int openpam_ttyconv(int _n,
246	const struct pam_message **_msg,
247	struct pam_response **_resp,
248	void *_data);
249
250extern int openpam_ttyconv_timeout;
251
252/*
253 * Null conversation function
254 */
255int openpam_nullconv(int _n,
256	const struct pam_message **_msg,
257	struct pam_response **_resp,
258	void *_data);
259
260/*
261 * PAM primitives
262 */
263enum {
264	PAM_SM_AUTHENTICATE,
265	PAM_SM_SETCRED,
266	PAM_SM_ACCT_MGMT,
267	PAM_SM_OPEN_SESSION,
268	PAM_SM_CLOSE_SESSION,
269	PAM_SM_CHAUTHTOK,
270	/* keep this last */
271	PAM_NUM_PRIMITIVES
272};
273
274/*
275 * Dummy service module function
276 */
277#define PAM_SM_DUMMY(type)						\
278PAM_EXTERN int								\
279pam_sm_##type(pam_handle_t *pamh, int flags,				\
280    int argc, const char *argv[])					\
281{									\
282									\
283	(void)pamh;							\
284	(void)flags;							\
285	(void)argc;							\
286	(void)argv;							\
287	return (PAM_IGNORE);						\
288}
289
290/*
291 * PAM service module functions match this typedef
292 */
293struct pam_handle;
294typedef int (*pam_func_t)(struct pam_handle *, int, int, const char **);
295
296/*
297 * A struct that describes a module.
298 */
299typedef struct pam_module pam_module_t;
300struct pam_module {
301	char		*path;
302	pam_func_t	 func[PAM_NUM_PRIMITIVES];
303	void		*dlh;
304};
305
306/*
307 * Source-code compatibility with Linux-PAM modules
308 */
309#if defined(PAM_SM_AUTH) || defined(PAM_SM_ACCOUNT) || \
310	defined(PAM_SM_SESSION) || defined(PAM_SM_PASSWORD)
311# define LINUX_PAM_MODULE
312#endif
313
314#if defined(LINUX_PAM_MODULE) && !defined(PAM_SM_AUTH)
315# define _PAM_SM_AUTHENTICATE	0
316# define _PAM_SM_SETCRED	0
317#else
318# undef PAM_SM_AUTH
319# define PAM_SM_AUTH
320# define _PAM_SM_AUTHENTICATE	pam_sm_authenticate
321# define _PAM_SM_SETCRED	pam_sm_setcred
322#endif
323
324#if defined(LINUX_PAM_MODULE) && !defined(PAM_SM_ACCOUNT)
325# define _PAM_SM_ACCT_MGMT	0
326#else
327# undef PAM_SM_ACCOUNT
328# define PAM_SM_ACCOUNT
329# define _PAM_SM_ACCT_MGMT	pam_sm_acct_mgmt
330#endif
331
332#if defined(LINUX_PAM_MODULE) && !defined(PAM_SM_SESSION)
333# define _PAM_SM_OPEN_SESSION	0
334# define _PAM_SM_CLOSE_SESSION	0
335#else
336# undef PAM_SM_SESSION
337# define PAM_SM_SESSION
338# define _PAM_SM_OPEN_SESSION	pam_sm_open_session
339# define _PAM_SM_CLOSE_SESSION	pam_sm_close_session
340#endif
341
342#if defined(LINUX_PAM_MODULE) && !defined(PAM_SM_PASSWORD)
343# define _PAM_SM_CHAUTHTOK	0
344#else
345# undef PAM_SM_PASSWORD
346# define PAM_SM_PASSWORD
347# define _PAM_SM_CHAUTHTOK	pam_sm_chauthtok
348#endif
349
350/*
351 * Infrastructure for static modules using GCC linker sets.
352 * You are not expected to understand this.
353 */
354#if !defined(PAM_SOEXT)
355# define PAM_SOEXT ".so"
356#endif
357
358#if defined(OPENPAM_STATIC_MODULES)
359# if !defined(__GNUC__)
360#  error "Don't know how to build static modules on non-GNU compilers"
361# endif
362/* gcc, static linking */
363# include <sys/cdefs.h>
364# include <linker_set.h>
365# define PAM_EXTERN static
366# define PAM_MODULE_ENTRY(name)						\
367	static char _pam_name[] = name PAM_SOEXT;			\
368	static struct pam_module _pam_module = {			\
369		.path = _pam_name,					\
370		.func = {						\
371			[PAM_SM_AUTHENTICATE] = _PAM_SM_AUTHENTICATE,	\
372			[PAM_SM_SETCRED] = _PAM_SM_SETCRED,		\
373			[PAM_SM_ACCT_MGMT] = _PAM_SM_ACCT_MGMT,		\
374			[PAM_SM_OPEN_SESSION] = _PAM_SM_OPEN_SESSION,	\
375			[PAM_SM_CLOSE_SESSION] = _PAM_SM_CLOSE_SESSION, \
376			[PAM_SM_CHAUTHTOK] = _PAM_SM_CHAUTHTOK		\
377		},							\
378	};								\
379	DATA_SET(_openpam_static_modules, _pam_module)
380#else
381/* normal case */
382# define PAM_EXTERN
383# define PAM_MODULE_ENTRY(name)
384#endif
385
386#ifdef __cplusplus
387}
388#endif
389
390#endif /* !SECURITY_OPENPAM_H_INCLUDED */
391