2 Unix SMB/CIFS implementation.
4 A localauth plugin for MIT Kerberos
6 Copyright (C) 2018 Andreas Schneider <asn@samba.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <krb5/localauth_plugin.h>
29 struct krb5_localauth_moddata_st
{
30 struct wbcContext
*wbc_ctx
;
34 * Initialize the module data.
36 * This creates the wbclient context.
38 static krb5_error_code
winbind_init(krb5_context context
,
39 krb5_localauth_moddata
*data
)
41 krb5_localauth_moddata d
;
44 d
= malloc(sizeof(struct krb5_localauth_moddata_st
));
49 d
->wbc_ctx
= wbcCtxCreate();
50 if (d
->wbc_ctx
== NULL
) {
55 wbcSetClientProcessName("krb5_localauth_plugin");
63 * Release resources used by module data.
65 static void winbind_fini(krb5_context context
, krb5_localauth_moddata data
)
67 wbcCtxFree(data
->wbc_ctx
);
73 * Determine whether aname is authorized to log in as the local account lname.
75 * Return 0 if aname is authorized, EPERM if aname is authoritatively not
76 * authorized, KRB5_PLUGIN_NO_HANDLE if the module cannot determine whether
77 * aname is authorized, and any other error code for a serious failure to
78 * process the request. aname will be considered authorized if at least one
79 * module returns 0 and all other modules return KRB5_PLUGIN_NO_HANDLE.
81 static krb5_error_code
winbind_userok(krb5_context context
,
82 krb5_localauth_moddata data
,
83 krb5_const_principal aname
,
86 krb5_error_code code
= 0;
87 char *princ_str
= NULL
;
88 struct passwd
*pwd
= NULL
;
89 uid_t princ_uid
= (uid_t
)-1;
90 uid_t lname_uid
= (uid_t
)-1;
94 code
= krb5_unparse_name(context
, aname
, &princ_str
);
99 cmp
= strcasecmp(princ_str
, lname
);
104 wbc_status
= wbcCtxGetpwnam(data
->wbc_ctx
,
107 switch (wbc_status
) {
108 case WBC_ERR_SUCCESS
:
109 princ_uid
= pwd
->pw_uid
;
112 case WBC_ERR_UNKNOWN_USER
:
113 /* match other insane libwbclient return codes */
114 case WBC_ERR_WINBIND_NOT_AVAILABLE
:
115 case WBC_ERR_DOMAIN_NOT_FOUND
:
116 case WBC_ERR_NOT_MAPPED
:
117 code
= KRB5_PLUGIN_NO_HANDLE
;
129 wbc_status
= wbcCtxGetpwnam(data
->wbc_ctx
,
132 switch (wbc_status
) {
133 case WBC_ERR_SUCCESS
:
134 lname_uid
= pwd
->pw_uid
;
136 case WBC_ERR_UNKNOWN_USER
:
137 /* match other insane libwbclient return codes */
138 case WBC_ERR_WINBIND_NOT_AVAILABLE
:
139 case WBC_ERR_DOMAIN_NOT_FOUND
:
140 case WBC_ERR_NOT_MAPPED
:
141 code
= KRB5_PLUGIN_NO_HANDLE
;
152 if (princ_uid
!= lname_uid
) {
156 com_err("winbind_localauth",
158 "Access %s: %s (uid=%u) %sequal to %s (uid=%u)",
159 code
== 0 ? "granted" : "denied",
161 (unsigned int)princ_uid
,
162 code
== 0 ? "" : "not ",
164 (unsigned int)lname_uid
);
167 krb5_free_unparsed_name(context
, princ_str
);
173 * Determine the local account name corresponding to aname.
175 * Return 0 and set *lname_out if a mapping can be determined; the contents of
176 * *lname_out will later be released with a call to the module's free_string
177 * method. Return KRB5_LNAME_NOTRANS if no mapping can be determined. Return
178 * any other error code for a serious failure to process the request; this will
179 * halt the krb5_aname_to_localname operation.
181 * If the module's an2ln_types field is set, this method will only be invoked
182 * when a profile "auth_to_local" value references one of the module's types.
183 * type and residual will be set to the type and residual of the auth_to_local
186 * If the module's an2ln_types field is not set but the an2ln method is
187 * implemented, this method will be invoked independently of the profile's
188 * auth_to_local settings, with type and residual set to NULL. If multiple
189 * modules are registered with an2ln methods but no an2ln_types field, the
190 * order of invocation is not defined, but all such modules will be consulted
191 * before the built-in mechanisms are tried.
193 static krb5_error_code
winbind_an2ln(krb5_context context
,
194 krb5_localauth_moddata data
,
196 const char *residual
,
197 krb5_const_principal aname
,
200 krb5_error_code code
= 0;
201 char *princ_str
= NULL
;
203 struct passwd
*pwd
= NULL
;
206 code
= krb5_unparse_name(context
, aname
, &princ_str
);
211 wbc_status
= wbcCtxGetpwnam(data
->wbc_ctx
,
214 krb5_free_unparsed_name(context
, princ_str
);
215 switch (wbc_status
) {
216 case WBC_ERR_SUCCESS
:
217 name
= strdup(pwd
->pw_name
);
220 case WBC_ERR_UNKNOWN_USER
:
221 /* match other insane libwbclient return codes */
222 case WBC_ERR_WINBIND_NOT_AVAILABLE
:
223 case WBC_ERR_DOMAIN_NOT_FOUND
:
224 case WBC_ERR_NOT_MAPPED
:
225 code
= KRB5_LNAME_NOTRANS
;
246 * Release the memory returned by an invocation of an2ln.
248 static void winbind_free_string(krb5_context context
,
249 krb5_localauth_moddata data
,
255 _PUBLIC_ krb5_error_code
256 localauth_winbind_initvt(krb5_context context
,
259 krb5_plugin_vtable vtable
);
261 _PUBLIC_ krb5_error_code
262 localauth_winbind_initvt(krb5_context context
,
265 krb5_plugin_vtable vtable
)
267 krb5_localauth_vtable vt
= (krb5_localauth_vtable
)vtable
;
270 com_err("winbind_localauth",
272 "Failed to load, plugin API changed.");
273 return KRB5_PLUGIN_VER_NOTSUPP
;
276 vt
->init
= winbind_init
;
277 vt
->fini
= winbind_fini
;
278 vt
->name
= "winbind";
279 vt
->an2ln
= winbind_an2ln
;
280 vt
->userok
= winbind_userok
;
281 vt
->free_string
= winbind_free_string
;