]> git.pld-linux.org Git - packages/autofs.git/blob - autofs-5.0.2-external-cred-cache.patch
- rel.1, lets try
[packages/autofs.git] / autofs-5.0.2-external-cred-cache.patch
1 diff --git a/CHANGELOG b/CHANGELOG
2 index 85af0ad..fcfbe62 100644
3 --- a/CHANGELOG
4 +++ b/CHANGELOG
5 @@ -50,6 +50,7 @@
6  - fix off-by-one error for lookup of map keys exactly 255 characters long.
7  - improve handling of server not available.
8  - fix LDAP_URI server selection.
9 +- add authentication option for using an external credential cache.
10  
11  18/06/2007 autofs-5.0.2
12  -----------------------
13 diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
14 index 5b5c475..d6a754d 100644
15 --- a/include/lookup_ldap.h
16 +++ b/include/lookup_ldap.h
17 @@ -67,10 +67,10 @@ struct lookup_context {
18         char        *user;
19         char        *secret;
20         char        *client_princ;
21 +       char        *client_cc;
22         int          kinit_done;
23         int          kinit_successful;
24  #ifdef WITH_SASL
25 -       krb5_principal  krb5_client_princ;
26         krb5_context krb5ctxt;
27         krb5_ccache  krb5_ccache;
28         sasl_conn_t  *sasl_conn;
29 diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c
30 index 303b7f2..f24f46b 100644
31 --- a/modules/cyrus-sasl.c
32 +++ b/modules/cyrus-sasl.c
33 @@ -72,6 +72,7 @@
34   */
35  static const char *krb5ccenv = "KRB5CCNAME";
36  static const char *krb5ccval = "MEMORY:_autofstkt";
37 +static const char *default_client = "autofsclient";
38  static pthread_mutex_t krb5cc_mutex = PTHREAD_MUTEX_INITIALIZER;
39  static unsigned int krb5cc_in_use = 0;
40  
41 @@ -376,7 +377,7 @@ int
42  sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
43  {
44         krb5_error_code ret;
45 -       krb5_principal tgs_princ, krb5_client_princ = ctxt->krb5_client_princ;
46 +       krb5_principal tgs_princ, krb5_client_princ;
47         krb5_creds my_creds;
48         char *tgs_name;
49         int status;
50 @@ -386,8 +387,8 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
51         ctxt->kinit_done = 1;
52  
53         debug(logopt,
54 -             "initializing kerberos ticket: client principal %s ",
55 -             ctxt->client_princ ? ctxt->client_princ : "autofsclient");
56 +             "initializing kerberos ticket: client principal %s",
57 +             ctxt->client_princ ? ctxt->client_princ : default_client);
58  
59         ret = krb5_init_context(&ctxt->krb5ctxt);
60         if (ret) {
61 @@ -424,13 +425,12 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
62                       "calling krb5_sname_to_principal using defaults");
63  
64                 ret = krb5_sname_to_principal(ctxt->krb5ctxt, NULL,
65 -                                       "autofsclient", KRB5_NT_SRV_HST, 
66 +                                       default_client, KRB5_NT_SRV_HST, 
67                                         &krb5_client_princ);
68                 if (ret) {
69                         error(logopt,
70                               "krb5_sname_to_principal failed for "
71 -                             "%s with error %d",
72 -                             ctxt->client_princ ? "" : "autofsclient", ret);
73 +                             "%s with error %d", default_client, ret);
74                         goto out_cleanup_cc;
75                 }
76  
77 @@ -441,11 +441,11 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
78                         debug(logopt,
79                               "krb5_unparse_name failed with error %d",
80                               ret);
81 -                       goto out_cleanup_cc;
82 +                       goto out_cleanup_client_princ;
83                 }
84  
85                 debug(logopt,
86 -                     "principal used for authentication: \"%s\"", tmp_name);
87 +                     "principal used for authentication: %s", tmp_name);
88  
89                 krb5_free_unparsed_name(ctxt->krb5ctxt, tmp_name);
90         }
91 @@ -461,14 +461,14 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
92         if (ret) {
93                 error(logopt,
94                       "krb5_build_principal failed with error %d", ret);
95 -               goto out_cleanup_cc;
96 +               goto out_cleanup_client_princ;
97         }
98  
99         ret = krb5_unparse_name(ctxt->krb5ctxt, tgs_princ, &tgs_name);
100         if (ret) {
101                 error(logopt, "krb5_unparse_name failed with error %d",
102                       ret);
103 -               goto out_cleanup_cc;
104 +               goto out_cleanup_client_princ;
105         }
106  
107         debug(logopt, "Using tgs name %s", tgs_name);
108 @@ -486,7 +486,6 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
109                 goto out_cleanup_unparse;
110         }
111  
112 -
113         status = pthread_mutex_lock(&krb5cc_mutex);
114         if (status)
115                 fatal(status);
116 @@ -503,7 +502,7 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
117         if (ret) {
118                 error(logopt,
119                       "krb5_cc_initialize failed with error %d", ret);
120 -               goto out_cleanup_unparse;
121 +               goto out_cleanup_creds;
122         }
123  
124         /* and store credentials for that principal */
125 @@ -511,26 +510,34 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
126         if (ret) {
127                 error(logopt,
128                       "krb5_cc_store_cred failed with error %d", ret);
129 -               goto out_cleanup_unparse;
130 +               goto out_cleanup_creds;
131         }
132  
133         /* finally, set the environment variable to point to our
134          * credentials cache */
135         if (setenv(krb5ccenv, krb5ccval, 1) != 0) {
136                 error(logopt, "setenv failed with %d", errno);
137 -               goto out_cleanup_unparse;
138 +               goto out_cleanup_creds;
139         }
140         ctxt->kinit_successful = 1;
141  
142         debug(logopt, "Kerberos authentication was successful!");
143  
144         krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name);
145 +       krb5_free_cred_contents(ctxt->krb5ctxt, &my_creds);
146 +       krb5_free_principal(ctxt->krb5ctxt, tgs_princ);
147 +       krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ);
148  
149         return 0;
150  
151 -out_cleanup_unparse:
152 +out_cleanup_creds:
153         krb5cc_in_use--;
154 +       krb5_free_cred_contents(ctxt->krb5ctxt, &my_creds);
155 +out_cleanup_unparse:
156 +       krb5_free_principal(ctxt->krb5ctxt, tgs_princ);
157         krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name);
158 +out_cleanup_client_princ:
159 +       krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ);
160  out_cleanup_cc:
161         status = pthread_mutex_lock(&krb5cc_mutex);
162         if (status)
163 @@ -554,6 +561,152 @@ out_cleanup_cc:
164  }
165  
166  /*
167 + *  Check a client given external credential cache.
168 + *
169 + *  Returns 0 upon success.  ctxt->kinit_done and ctxt->kinit_successful
170 + *  are set for cleanup purposes.  The krb5 context and ccache entries in
171 + *  the lookup_context are also filled in.
172 + *
173 + *  Upon failure, -1 is returned.
174 + */
175 +int
176 +sasl_do_kinit_ext_cc(unsigned logopt, struct lookup_context *ctxt)
177 +{
178 +       krb5_principal def_princ;
179 +       krb5_principal krb5_client_princ;
180 +       krb5_error_code ret;
181 +       char *cc_princ, *client_princ;
182 +
183 +       if (ctxt->kinit_done)
184 +               return 0;
185 +       ctxt->kinit_done = 1;
186 +
187 +       debug(logopt,
188 +             "using external credential cache for auth: client principal %s",
189 +             ctxt->client_princ ? ctxt->client_princ : default_client);
190 +
191 +       ret = krb5_init_context(&ctxt->krb5ctxt);
192 +       if (ret) {
193 +               error(logopt, "krb5_init_context failed with %d", ret);
194 +               return -1;
195 +       }
196 +
197 +       ret = krb5_cc_resolve(ctxt->krb5ctxt, ctxt->client_cc, &ctxt->krb5_ccache);
198 +       if (ret) {
199 +               error(logopt, "krb5_cc_resolve failed with error %d",
200 +                     ret);
201 +               krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
202 +               krb5_free_context(ctxt->krb5ctxt);
203 +               return -1;
204 +       }
205 +
206 +       ret = krb5_cc_get_principal(ctxt->krb5ctxt, ctxt->krb5_ccache, &def_princ);
207 +       if (ret) {
208 +               error(logopt, "krb5_cc_get_principal failed with error %d", ret);
209 +               krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
210 +               krb5_free_context(ctxt->krb5ctxt);
211 +               return -1;
212 +       }
213 +
214 +       ret = krb5_unparse_name(ctxt->krb5ctxt, def_princ, &cc_princ);
215 +       if (ret) {
216 +               error(logopt, "krb5_unparse_name failed with error %d", ret);
217 +               krb5_free_principal(ctxt->krb5ctxt, def_princ);
218 +               krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
219 +               krb5_free_context(ctxt->krb5ctxt);
220 +               return -1;
221 +       }
222 +
223 +       debug(logopt, "external credential cache default principal %s", cc_princ);
224 +
225 +       /*
226 +        * If the principal isn't set in the config construct the default
227 +        * so we can check against the default principal of the external
228 +        * cred cache.
229 +        */
230 +       if (ctxt->client_princ)
231 +               client_princ = ctxt->client_princ;
232 +       else {
233 +               debug(logopt,
234 +                     "calling krb5_sname_to_principal using defaults");
235 +
236 +               ret = krb5_sname_to_principal(ctxt->krb5ctxt, NULL,
237 +                                       default_client, KRB5_NT_SRV_HST, 
238 +                                       &krb5_client_princ);
239 +               if (ret) {
240 +                       error(logopt,
241 +                             "krb5_sname_to_principal failed for "
242 +                             "%s with error %d", default_client, ret);
243 +                       krb5_free_principal(ctxt->krb5ctxt, def_princ);
244 +                       krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
245 +                       krb5_free_context(ctxt->krb5ctxt);
246 +                       return -1;
247 +               }
248 +
249 +
250 +               ret = krb5_unparse_name(ctxt->krb5ctxt,
251 +                                       krb5_client_princ, &client_princ);
252 +               if (ret) {
253 +                       debug(logopt,
254 +                             "krb5_unparse_name failed with error %d",
255 +                             ret);
256 +                       krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ);
257 +                       krb5_free_principal(ctxt->krb5ctxt, def_princ);
258 +                       krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
259 +                       krb5_free_context(ctxt->krb5ctxt);
260 +                       return -1;
261 +               }
262 +
263 +               debug(logopt,
264 +                     "principal used for authentication: %s", client_princ);
265 +
266 +               krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ);
267 +       }
268 +
269 +       /*
270 +        * Check if the principal to be used matches the default principal in
271 +        * the external cred cache.
272 +        */
273 +       if (strcmp(cc_princ, client_princ)) {
274 +               error(logopt,
275 +                     "configured client principal %s ",
276 +                     ctxt->client_princ);
277 +               error(logopt,
278 +                     "external credential cache default principal %s",
279 +                     cc_princ);
280 +               error(logopt, 
281 +                     "cannot use credential cache, external "
282 +                     "default principal does not match configured "
283 +                     "principal");
284 +               if (!ctxt->client_princ)
285 +                       krb5_free_unparsed_name(ctxt->krb5ctxt, client_princ);
286 +               krb5_free_unparsed_name(ctxt->krb5ctxt, cc_princ);
287 +               krb5_free_principal(ctxt->krb5ctxt, def_princ);
288 +               krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
289 +               krb5_free_context(ctxt->krb5ctxt);
290 +               return -1;
291 +       }
292 +
293 +       if (!ctxt->client_princ)
294 +               krb5_free_unparsed_name(ctxt->krb5ctxt, client_princ);
295 +       krb5_free_unparsed_name(ctxt->krb5ctxt, cc_princ);
296 +       krb5_free_principal(ctxt->krb5ctxt, def_princ);
297 +
298 +       /* Set the environment variable to point to the external cred cache */
299 +       if (setenv(krb5ccenv, ctxt->client_cc, 1) != 0) {
300 +               error(logopt, "setenv failed with %d", errno);
301 +               krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
302 +               krb5_free_context(ctxt->krb5ctxt);
303 +               return -1;
304 +       }
305 +       ctxt->kinit_successful = 1;
306 +
307 +       debug(logopt, "Kerberos authentication was successful!");
308 +
309 +       return 0;
310 +}
311 +
312 +/*
313   *  Attempt to bind to the ldap server using a given authentication
314   *  mechanism.  ldap should be a properly initialzed ldap pointer.
315   *
316 @@ -570,7 +723,11 @@ sasl_bind_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const c
317         int result;
318  
319         if (!strncmp(mech, "GSSAPI", 6)) {
320 -               if (sasl_do_kinit(logopt, ctxt) != 0)
321 +               if (ctxt->client_cc)
322 +                       result = sasl_do_kinit_ext_cc(logopt, ctxt);
323 +               else
324 +                       result = sasl_do_kinit(logopt, ctxt);
325 +               if (result != 0)
326                         return NULL;
327         }
328  
329 @@ -774,7 +931,7 @@ autofs_sasl_done(struct lookup_context *ctxt)
330                 if (status)
331                         fatal(status);
332  
333 -               if (--krb5cc_in_use)
334 +               if (--krb5cc_in_use || ctxt->client_cc)
335                         ret = krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
336                 else 
337                         ret = krb5_cc_destroy(ctxt->krb5ctxt, ctxt->krb5_ccache);
338 diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
339 index 93f0477..13fbff7 100644
340 --- a/modules/lookup_ldap.c
341 +++ b/modules/lookup_ldap.c
342 @@ -651,7 +651,7 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
343         xmlNodePtr   root = NULL;
344         char         *authrequired, *auth_conf, *authtype;
345         char         *user = NULL, *secret = NULL;
346 -       char         *client_princ = NULL;
347 +       char         *client_princ = NULL, *client_cc = NULL;
348         char         *usetls, *tlsrequired;
349  
350         authtype = user = secret = NULL;
351 @@ -840,6 +840,7 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
352          * client.  The default is "autofsclient/hostname@REALM".
353          */
354         (void)get_property(logopt, root, "clientprinc", &client_princ);
355 +       (void)get_property(logopt, root, "credentialcache", &client_cc);
356  
357         ctxt->auth_conf = auth_conf;
358         ctxt->use_tls = use_tls;
359 @@ -851,6 +852,7 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
360         ctxt->user = user;
361         ctxt->secret = secret;
362         ctxt->client_princ = client_princ;
363 +       ctxt->client_cc = client_cc;
364  
365         debug(logopt, MODPREFIX
366               "ldap authentication configured with the following options:");
367 @@ -863,9 +865,10 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
368         debug(logopt, MODPREFIX
369               "user: %s, "
370               "secret: %s, "
371 -             "client principal: %s",
372 +             "client principal: %s "
373 +             "credential cache: %s",
374               user, secret ? "specified" : "unspecified",
375 -             client_princ);
376 +             client_princ, client_cc);
377  
378  out:
379         xmlFreeDoc(doc);
380 @@ -1128,6 +1131,8 @@ static void free_context(struct lookup_context *ctxt)
381                 free(ctxt->secret);
382         if (ctxt->client_princ)
383                 free(ctxt->client_princ);
384 +       if (ctxt->client_cc)
385 +               free(ctxt->client_cc);
386         if (ctxt->mapname)
387                 free(ctxt->mapname);
388         if (ctxt->qdn)
389 diff --git a/samples/autofs_ldap_auth.conf b/samples/autofs_ldap_auth.conf
390 index e10d1ea..a1f60c0 100644
391 --- a/samples/autofs_ldap_auth.conf
392 +++ b/samples/autofs_ldap_auth.conf
393 @@ -56,6 +56,11 @@ clientprinc  -  When using GSSAPI authentication, this attribute is
394             consulted to determine the principal name to use when
395             authenticating to the directory server.  By default, this will
396             be set to "autofsclient/<fqdn>@<REALM>.
397 +
398 +credentialcache - When using GSSAPI authentication, this attribute
399 +           can be used to specify an externally configured credential
400 +           cache that is used during authentication. By default, autofs
401 +           will setup a memory based credential cache.
402  -->
403  
404  <autofs_ldap_sasl_conf
This page took 0.077136 seconds and 3 git commands to generate.