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) {
61 * Release resources used by module data.
63 static void winbind_fini(krb5_context context, krb5_localauth_moddata data)
65 wbcCtxFree(data->wbc_ctx);
71 * Determine whether aname is authorized to log in as the local account lname.
73 * Return 0 if aname is authorized, EPERM if aname is authoritatively not
74 * authorized, KRB5_PLUGIN_NO_HANDLE if the module cannot determine whether
75 * aname is authorized, and any other error code for a serious failure to
76 * process the request. aname will be considered authorized if at least one
77 * module returns 0 and all other modules return KRB5_PLUGIN_NO_HANDLE.
79 static krb5_error_code winbind_userok(krb5_context context,
80 krb5_localauth_moddata data,
81 krb5_const_principal aname,
84 krb5_error_code code = 0;
85 char *princ_str = NULL;
86 struct passwd *pwd = NULL;
92 code = krb5_unparse_name(context, aname, &princ_str);
97 cmp = strcasecmp(princ_str, lname);
99 krb5_free_unparsed_name(context, princ_str);
103 wbc_status = wbcCtxGetpwnam(data->wbc_ctx,
106 krb5_free_unparsed_name(context, princ_str);
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 code = KRB5_PLUGIN_NO_HANDLE;
127 wbc_status = wbcCtxGetpwnam(data->wbc_ctx,
130 switch (wbc_status) {
131 case WBC_ERR_SUCCESS:
132 lname_uid = pwd->pw_uid;
134 case WBC_ERR_UNKNOWN_USER:
135 /* match other insane libwbclient return codes */
136 case WBC_ERR_WINBIND_NOT_AVAILABLE:
137 case WBC_ERR_DOMAIN_NOT_FOUND:
138 code = KRB5_PLUGIN_NO_HANDLE;
149 if (princ_uid != lname_uid) {
157 * Determine the local account name corresponding to aname.
159 * Return 0 and set *lname_out if a mapping can be determined; the contents of
160 * *lname_out will later be released with a call to the module's free_string
161 * method. Return KRB5_LNAME_NOTRANS if no mapping can be determined. Return
162 * any other error code for a serious failure to process the request; this will
163 * halt the krb5_aname_to_localname operation.
165 * If the module's an2ln_types field is set, this method will only be invoked
166 * when a profile "auth_to_local" value references one of the module's types.
167 * type and residual will be set to the type and residual of the auth_to_local
170 * If the module's an2ln_types field is not set but the an2ln method is
171 * implemented, this method will be invoked independently of the profile's
172 * auth_to_local settings, with type and residual set to NULL. If multiple
173 * modules are registered with an2ln methods but no an2ln_types field, the
174 * order of invocation is not defined, but all such modules will be consulted
175 * before the built-in mechanisms are tried.
177 static krb5_error_code winbind_an2ln(krb5_context context,
178 krb5_localauth_moddata data,
180 const char *residual,
181 krb5_const_principal aname,
184 krb5_error_code code = 0;
185 char *princ_str = NULL;
187 struct passwd *pwd = NULL;
190 code = krb5_unparse_name(context, aname, &princ_str);
195 wbc_status = wbcCtxGetpwnam(data->wbc_ctx,
198 krb5_free_unparsed_name(context, princ_str);
199 switch (wbc_status) {
200 case WBC_ERR_SUCCESS:
201 name = strdup(pwd->pw_name);
204 case WBC_ERR_UNKNOWN_USER:
205 /* match other insane libwbclient return codes */
206 case WBC_ERR_WINBIND_NOT_AVAILABLE:
207 case WBC_ERR_DOMAIN_NOT_FOUND:
208 code = KRB5_LNAME_NOTRANS;
229 * Release the memory returned by an invocation of an2ln.
231 static void winbind_free_string(krb5_context context,
232 krb5_localauth_moddata data,
239 localauth_winbind_initvt(krb5_context context,
242 krb5_plugin_vtable vtable);
245 localauth_winbind_initvt(krb5_context context,
248 krb5_plugin_vtable vtable)
250 krb5_localauth_vtable vt = (krb5_localauth_vtable)vtable;
253 com_err("winbind_localauth",
255 "Failed to load, plugin API changed.");
256 return KRB5_PLUGIN_VER_NOTSUPP;
259 vt->init = winbind_init;
260 vt->fini = winbind_fini;
261 vt->name = "winbind";
262 vt->an2ln = winbind_an2ln;
263 vt->userok = winbind_userok;
264 vt->free_string = winbind_free_string;