1 /*
2  * Copyright 2006,2008,2012,2014 Red Hat, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, and the entire permission notice in its entirety,
9  *    including the disclaimer of warranties.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote
14  *    products derived from this software without specific prior
15  *    written permission.
16  *
17  * ALTERNATIVELY, this product may be distributed under the terms of the
18  * GNU Lesser General Public License, in which case the provisions of the
19  * LGPL are required INSTEAD OF the above restrictions.
20  *
21  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
24  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "../config.h"
34 
35 #ifdef HAVE_SECURITY_PAM_APPL_H
36 #include <security/pam_appl.h>
37 #endif
38 
39 #ifdef HAVE_SECURITY_PAM_MODULES_H
40 #define PAM_SM_SESSION
41 #include <security/pam_modules.h>
42 #endif
43 
44 #include <limits.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 
50 #include KRB5_H
51 
52 #include "init.h"
53 #include "log.h"
54 #include "minikafs.h"
55 #include "options.h"
56 #include "prompter.h"
57 #include "shmem.h"
58 #include "stash.h"
59 #include "tokens.h"
60 #include "userinfo.h"
61 #include "v5.h"
62 #include "xstr.h"
63 
64 static int
maybe_setpag(const char * fn,pam_handle_t * pamh,int flags,int argc,PAM_KRB5_MAYBE_CONST char ** argv)65 maybe_setpag(const char *fn, pam_handle_t *pamh, int flags,
66 	     int argc, PAM_KRB5_MAYBE_CONST char **argv)
67 {
68 	krb5_context ctx;
69 	struct _pam_krb5_options *options;
70 	int i, ret;
71 
72 	/* Initialize Kerberos. */
73 	if (_pam_krb5_init_ctx(&ctx, argc, argv) != 0) {
74 		warn("error initializing Kerberos");
75 		return PAM_SERVICE_ERR;
76 	}
77 
78 	/* Read our options. */
79 	options = _pam_krb5_options_init(pamh, argc, argv, ctx,
80 					 _pam_krb5_option_role_general);
81 	if (options == NULL) {
82 		warn("error parsing options (shouldn't happen)");
83 		_pam_krb5_free_ctx(ctx);
84 		return PAM_SERVICE_ERR;
85 	}
86 
87 	if (options->ignore_afs) {
88 		/* Do what we were told. */
89 		ret = PAM_IGNORE;
90 	} else {
91 		if (!minikafs_has_afs()) {
92 			/* Do nothing. */
93 			if (options->debug) {
94 				debug("%s did not detect AFS, "
95 				      "not creating new PAG", fn);
96 			}
97 			ret = PAM_IGNORE;
98 		} else {
99 			/* Create a PAG. */
100 			if (options->debug) {
101 				debug("%s detects AFS, creating new PAG", fn);
102 			}
103 			i = minikafs_setpag();
104 			if (i != 0) {
105 				if (options->debug) {
106 					debug("error creating new PAG: %s",
107 					      strerror(i));
108 				}
109 				ret = PAM_SERVICE_ERR;
110 			} else {
111 				ret = PAM_SUCCESS;
112 			}
113 		}
114 	}
115 
116 	if (options->debug) {
117 		debug("%s returning %d (%s)",
118 		      fn,
119 		      ret,
120 		      pam_strerror(pamh, ret));
121 	}
122 	_pam_krb5_options_free(pamh, ctx, options);
123 	_pam_krb5_free_ctx(ctx);
124 	return ret;
125 }
126 
127 int
pam_sm_authenticate(pam_handle_t * pamh,int flags,int argc,PAM_KRB5_MAYBE_CONST char ** argv)128 pam_sm_authenticate(pam_handle_t *pamh, int flags,
129 		    int argc, PAM_KRB5_MAYBE_CONST char **argv)
130 {
131 	return PAM_IGNORE;
132 }
133 
134 int
pam_sm_setcred(pam_handle_t * pamh,int flags,int argc,PAM_KRB5_MAYBE_CONST char ** argv)135 pam_sm_setcred(pam_handle_t *pamh, int flags,
136 	       int argc, PAM_KRB5_MAYBE_CONST char **argv)
137 {
138 	if (flags & PAM_ESTABLISH_CRED) {
139 		return maybe_setpag("pam_setcred", pamh, flags, argc, argv);
140 	}
141 	return PAM_IGNORE;
142 }
143 
144 int
pam_sm_open_session(pam_handle_t * pamh,int flags,int argc,PAM_KRB5_MAYBE_CONST char ** argv)145 pam_sm_open_session(pam_handle_t *pamh, int flags,
146 		    int argc, PAM_KRB5_MAYBE_CONST char **argv)
147 {
148 	return maybe_setpag("pam_open_session", pamh, flags, argc, argv);
149 }
150 
151 int
pam_sm_close_session(pam_handle_t * pamh,int flags,int argc,PAM_KRB5_MAYBE_CONST char ** argv)152 pam_sm_close_session(pam_handle_t *pamh, int flags,
153 		     int argc, PAM_KRB5_MAYBE_CONST char **argv)
154 {
155 	return PAM_SUCCESS;
156 }
157