|
|
1.1 root 1: /* ds_bind.c - BindArgument Checking and Authentication */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_bind.c,v 7.2 90/03/15 11:18:46 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/quipu/RCS/ds_bind.c,v 7.2 90/03/15 11:18:46 mrose Exp $
9: *
10: *
11: * $Log: ds_bind.c,v $
12: * Revision 7.2 90/03/15 11:18:46 mrose
13: * quipu-sync
14: *
15: * Revision 7.1 89/12/19 16:20:13 mrose
16: * sync
17: *
18: * Revision 7.0 89/11/23 22:17:05 mrose
19: * Release 6.0
20: *
21: */
22:
23: /*
24: * NOTICE
25: *
26: * Acquisition, use, and distribution of this module and related
27: * materials are subject to the restrictions of a license agreement.
28: * Consult the Preface in the User's Manual for the full terms of
29: * this agreement.
30: *
31: */
32:
33:
34: #include "quipu/util.h"
35: #include "quipu/entry.h"
36: #include "quipu/commonarg.h"
37: #include "quipu/bind.h"
38: #include "quipu/compare.h"
39: #include "quipu/dua.h"
40: #include "quipu/connection.h"
41:
42: extern LLog * log_dsap;
43: extern DN mydsadn;
44: struct oper_act * oper_alloc();
45:
46: #ifndef NO_STATS
47: extern LLog * log_stat;
48: extern int dn_print ();
49: #endif
50:
51: int bind_window = 300; /* Tailorable timeout for credentials */
52:
53: int ds_bind_init (cn)
54: struct connection * cn;
55: {
56: struct ds_bind_arg * arg = &(cn->cn_start.cs_ds.ds_bind_arg);
57: struct ds_bind_arg * result = &(cn->cn_start.cs_res);
58: struct ds_bind_error * error = &(cn->cn_start.cs_err);
59: Attr_Sequence as;
60: Entry entryptr;
61: extern AttributeType at_password;
62: extern AttributeType at_p_password;
63: struct di_block * dsas;
64: struct di_block * di_tmp;
65: struct oper_act * on;
66: struct ds_compare_arg * cma;
67: struct DSError err;
68: static struct common_args ca_def = default_common_args;
69: int res;
70: int retval;
71: struct protected_password * pp;
72: #ifndef NO_STATS
73: char buff[LINESIZE];
74: #endif
75:
76: DLOG (log_dsap,LLOG_TRACE,("ds_bind_init"));
77:
78:
79: if (arg->dba_version != DBA_VERSION_V1988)
80: {
81: error->dbe_version = DBA_VERSION_V1988;
82: error->dbe_type = DBE_TYPE_SERVICE;
83: error->dbe_value = DSE_SV_UNAVAILABLE;
84: return(DS_ERROR_CONNECT);
85: }
86:
87: /* We don't support any bilaterally-defined authentication procedures.
88: * Hence, if we get EXTERNAL credentials in the bind, reject them.
89: */
90:
91: if (arg->dba_auth_type == DBA_AUTH_EXTERNAL)
92: {
93: DLOG(log_dsap, LLOG_EXCEPTIONS, ("EXTERNAL found in credentials"));
94: error->dbe_version = DBA_VERSION_V1988;
95: error->dbe_type = DBE_TYPE_SERVICE;
96: error->dbe_value = DSE_SV_UNAVAILABLE;
97: return (DS_ERROR_CONNECT);
98: }
99:
100: /* If password is present, but zero length, treat as though absent */
101: if ((arg->dba_auth_type == DBA_AUTH_SIMPLE) && (arg->dba_passwd_len == 0))
102: arg->dba_auth_type = DBA_AUTH_NONE;
103:
104:
105: /* If binding as NULLDN (ie. `anonymous') don't need any authentication */
106: if (arg->dba_dn == NULLDN)
107: {
108: #ifndef NO_STATS
109: LLOG(log_stat, LLOG_NOTICE, ("Bind (%d) (anonymous)", cn->cn_ad));
110: #endif
111: cn->cn_authen = DBA_AUTH_NONE;
112: make_dsa_bind_arg(result);
113: return(DS_OK);
114: }
115:
116: /* Now we're sure dba_dn contains a valid pointer, can decode it */
117:
118: switch (arg->dba_auth_type)
119: {
120: case DBA_AUTH_NONE:
121: #ifndef NO_STATS
122: (void) sprintf (buff,"Bind (%d) (no auth)",cn->cn_ad);
123: pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)arg->dba_dn);
124: #endif
125: cn->cn_authen = DBA_AUTH_NONE;
126: make_dsa_bind_arg(result);
127: return (DS_OK);
128: case DBA_AUTH_SIMPLE:
129: #ifndef NO_STATS
130: (void) sprintf (buff,"Bind (%d) (simple)",cn->cn_ad);
131: pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)arg->dba_dn);
132: #endif
133: /* Can't check simple credentials from DSP (livelock risk).
134: * Hence treat DSP accesses as unauthenticated.
135: */
136: if (cn->cn_ctx != DS_CTX_X500_DAP)
137: {
138: cn->cn_authen = DBA_AUTH_NONE;
139: make_dsa_bind_arg(result);
140: return(DS_OK);
141: }
142: break;
143: case DBA_AUTH_PROTECTED:
144: #ifndef NO_STATS
145: (void) sprintf (buff,"Bind (%d) (protected)",cn->cn_ad);
146: pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)arg->dba_dn);
147: #endif
148: if (cn->cn_ctx != DS_CTX_X500_DAP)
149: {
150: cn->cn_authen = DBA_AUTH_NONE;
151: make_dsa_bind_arg(result);
152: return(DS_OK);
153: }
154: else
155: {
156: UTC ut;
157: long c_time, s_time, delta;
158: time_t time();
159:
160: (void) time(&s_time);
161: ut = str2utct(arg->dba_time1, strlen(arg->dba_time1));
162: if (ut == NULLUTC)
163: c_time = 0L; /* 1970 is a convenient out-of-date timestamp */
164: else
165: c_time = gtime(ut2tm(ut));
166: delta = s_time - c_time;
167: if ((delta < 0) || (delta > bind_window))
168: {
169: DLOG(log_dsap, LLOG_EXCEPTIONS,
170: ("Time = %s, Delay = %D s : Association rejected",
171: arg->dba_time1, delta));
172: error->dbe_version = DBA_VERSION_V1988;
173: error->dbe_type = DBE_TYPE_SECURITY;
174: error->dbe_value = DSE_SC_INVALIDCREDENTIALS;
175: return (DS_ERROR_CONNECT);
176: }
177: pp = (struct protected_password *) calloc(1, sizeof(*pp));
178: /* Ought to check for null pointer ... */
179: pp->passwd = malloc((unsigned)arg->dba_passwd_len);
180: bcopy(arg->dba_passwd, pp->passwd, arg->dba_passwd_len);
181: pp->n_octets = arg->dba_passwd_len;
182: pp->time1 = strdup(arg->dba_time1);
183: pp->protected = (char) 1;
184: }
185: break;
186: case DBA_AUTH_STRONG:
187: #ifndef NO_STATS
188: (void) sprintf (buff,"Bind (%d) (strong)",cn->cn_ad);
189: pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)arg->dba_dn);
190: #endif
191: /* Strong authentication is not yet supported.
192: * It will eventually be possible to check strong credentials over DSP.
193: * For the moment, accept them and treat as NONE over DSP, but reject
194: * over DAP.
195: */
196: #ifdef HAVE_RSA
197: {
198: int rc;
199: DN real_name;
200: extern int encode_DAS_TokenToSign();
201:
202: rc = check_cert_path((caddr_t) arg, encode_DAS_TokenToSign,
203: arg->dba_cpath, arg->dba_sig, &real_name);
204: if (rc == OK)
205: {
206: make_dsa_bind_arg(result);
207: return (DS_OK);
208: }
209: else
210: {
211: error->dbe_version = DBA_VERSION_V1988;
212: error->dbe_type = DBE_TYPE_SECURITY;
213: error->dbe_value = rc;
214: return (DS_ERROR_CONNECT);
215: }
216: }
217: #else
218: if (cn->cn_ctx != DS_CTX_X500_DAP)
219: {
220: cn->cn_authen = DBA_AUTH_NONE;
221: make_dsa_bind_arg(result);
222: return (DS_OK);
223: }
224: else
225: {
226: error->dbe_version = DBA_VERSION_V1988;
227: error->dbe_type = DBE_TYPE_SERVICE;
228: error->dbe_value = DSE_SV_UNAVAILABLE;
229: return (DS_ERROR_CONNECT);
230: }
231: #endif
232: }
233:
234: /* If we fall through to here, credentials are simple or protected simple */
235:
236: if ((res = really_find_entry(arg->dba_dn, TRUE, NULLDNSEQ, FALSE, &(entryptr), &(err), &(dsas))) == DS_OK) {
237: /* is it really OK ??? */
238: if ((entryptr->e_data == E_TYPE_CONSTRUCTOR)
239: || (entryptr->e_data == E_TYPE_CACHE_FROM_MASTER)) {
240: DN dn_found;
241: DLOG(log_dsap, LLOG_NOTICE, ("rfe (bind) returned a constructor"));
242: dn_found = get_copy_dn(entryptr);
243: res = constructor_dsa_info(dn_found,NULLDNSEQ,FALSE,entryptr,&err,&dsas);
244: dn_free (dn_found);
245: }
246: }
247: switch(res)
248: {
249: case DS_OK:
250: /* entryptr filled out - break through to deal with it */
251: break;
252:
253: case DS_CONTINUE:
254: /*
255: * At this point a remote operation is required to compare
256: * the password given with the password of the entry, so
257: * fire up the remote operation and return without completing.
258: * Mark the operation as a BIND_COMPARE_OP and set the connection
259: * which will need to be restarted.
260: * Generate a compare argument.
261: * Chain the compare operation using the di_blocks.
262: */
263: cn->cn_start.cs_bind_compare = on = oper_alloc();/* cn knows about on */
264: on->on_type = ON_TYPE_BIND_COMPARE;
265: on->on_bind_compare = cn; /* on knows about cn */
266:
267: on->on_arg = &(on->on_req);
268: set_my_chain_args(&(on->on_req.dca_charg), arg->dba_dn);
269: on->on_req.dca_dsarg.arg_type = OP_COMPARE;
270: cma = &(on->on_req.dca_dsarg.arg_cm);
271:
272: cma->cma_common = ca_def; /* struct copy */
273:
274: /* Set originator/requestor */
275: on->on_req.dca_charg.cha_originator = dn_cpy(arg->dba_dn);
276: cma->cma_common.ca_requestor = dn_cpy(arg->dba_dn);
277: cma->cma_common.ca_servicecontrol.svc_prio = SVC_PRIO_HIGH;
278:
279: cma->cma_object = dn_cpy(arg->dba_dn);
280:
281: if (arg->dba_auth_type == DBA_AUTH_SIMPLE)
282: {
283: cma->cma_purported.ava_type = AttrT_cpy (at_password);
284: cma->cma_purported.ava_value =
285: str2AttrV (arg->dba_passwd,str2syntax("octetstring"));
286: }
287: else
288: {
289: cma->cma_purported.ava_type = AttrT_cpy (at_p_password);
290: cma->cma_purported.ava_value =
291: (AttributeValue) calloc(1, sizeof(attrVal));
292: cma->cma_purported.ava_value->av_syntax =
293: str2syntax("protectedPassword");
294: cma->cma_purported.ava_value->av_struct = (caddr_t) pp;
295: }
296:
297:
298: on->on_dsas = dsas;
299: for(di_tmp=on->on_dsas; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
300: {
301: di_tmp->di_type = DI_OPERATION;
302: di_tmp->di_oper = on;
303: }
304:
305: if(oper_chain(on) == OK)
306: return(DS_CONTINUE);
307:
308: oper_extract(on);
309: cn->cn_start.cs_bind_compare = NULLOPER;
310:
311: error->dbe_version = DBA_VERSION_V1988;
312: error->dbe_type = DBE_TYPE_SERVICE;
313: error->dbe_value = DSE_SV_UNAVAILABLE;
314:
315: return(DS_ERROR_CONNECT);
316:
317: case DS_X500_ERROR:
318: /* User's entry doesn't exist, for example */
319: LLOG(log_dsap, LLOG_NOTICE, ("ds_bind - really_find_entry erred:"));
320: log_ds_error(&(err));
321: ds_error_free(&(err));
322: error->dbe_version = DBA_VERSION_V1988;
323: error->dbe_type = DBE_TYPE_SECURITY;
324: error->dbe_value = DSE_SC_INVALIDCREDENTIALS;
325: return(DS_ERROR_CONNECT);
326:
327: default:
328: error->dbe_version = DBA_VERSION_V1988;
329: error->dbe_type = DBE_TYPE_SERVICE;
330: error->dbe_value = DSE_SV_DITERROR;
331: return(DS_ERROR_CONNECT);
332: }
333:
334: if ((as = as_find_type (entryptr->e_attributes,
335: (arg->dba_auth_type == DBA_AUTH_SIMPLE) ?
336: at_password : at_p_password)) == NULLATTR)
337: {
338: /* No password in entry.
339: * Simple authentication is not possible for entities without passwords.
340: * Hence, give the `inappropriate authentication' message.
341: */
342: error->dbe_version = DBA_VERSION_V1988;
343: error->dbe_type = DBE_TYPE_SECURITY;
344: error->dbe_value = DSE_SC_AUTHENTICATION;
345: return (DS_ERROR_CONNECT);
346: }
347:
348: if (arg->dba_auth_type == DBA_AUTH_SIMPLE) {
349: if (strlen ((char *)as->attr_value->avseq_av.av_struct) != arg->dba_passwd_len)
350: retval = -1;
351: else
352: retval = strncmp ((char *)as->attr_value->avseq_av.av_struct,
353: arg->dba_passwd, arg->dba_passwd_len);
354: } else
355: retval = check_guard(
356: ((struct protected_password *)
357: as->attr_value->avseq_av.av_struct)->passwd,
358: ((struct protected_password *)
359: as->attr_value->avseq_av.av_struct)->n_octets,
360: arg->dba_time1,
361: arg->dba_passwd,
362: arg->dba_passwd_len);
363:
364: if (retval == 0)
365: {
366: /* Password OK! */
367: cn->cn_authen = arg->dba_auth_type;
368: make_dsa_bind_arg(result);
369: return (DS_OK);
370: }
371: else
372: {
373: /* password wrong ! */
374: error->dbe_version = DBA_VERSION_V1988;
375: error->dbe_type = DBE_TYPE_SECURITY;
376: error->dbe_value = DSE_SC_INVALIDCREDENTIALS;
377: return (DS_ERROR_CONNECT);
378: }
379: }
380:
381: bind_compare_result_wakeup(on)
382: struct oper_act * on;
383: {
384:
385: DLOG(log_dsap, LLOG_TRACE, ("bind_compare_result_wakeup()"));
386: if(on->on_bind_compare == NULLCONN)
387: {
388: LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_result_wakeup - connection initiating compare already failed"));
389: }
390: else
391: {
392: if(on->on_resp.di_result.dr_res.dcr_dsres.res_cm.cmr_matched)
393: {
394: DLOG(log_dsap, LLOG_DEBUG, ("bind_compare - user authenticated"));
395: on->on_bind_compare->cn_authen = on->on_bind_compare->cn_connect.cc_req.dba_auth_type;
396: conn_init_res(on->on_bind_compare);
397: }
398: else
399: {
400: struct ds_bind_error * error = &(on->on_bind_compare->cn_start.cs_err);
401: DLOG(log_dsap, LLOG_DEBUG, ("bind_compare - user NOT authenticated"));
402: error->dbe_version = DBA_VERSION_V1988;
403: error->dbe_type = DBE_TYPE_SECURITY;
404: /* Password match failed, therefore credentials are wrong */
405: error->dbe_value = DSE_SC_INVALIDCREDENTIALS;
406: conn_init_err(on->on_bind_compare);
407: }
408: }
409: oper_conn_extract(on);
410: oper_free(on);
411: }
412:
413: bind_compare_error_wakeup(on)
414: struct oper_act * on;
415: {
416: int errmsg = DSE_SV_DITERROR;
417: int errtype = DBE_TYPE_SERVICE;
418:
419: DLOG(log_dsap, LLOG_TRACE, ("bind_compare_error_wakeup()"));
420:
421: /*
422: * Check for referral and rechain if appropriate;
423: * Otherwise check if error requires propagation
424: * or another of the original di_blocks to be chained to.
425: */
426:
427: if(on->on_bind_compare == NULLCONN)
428: {
429: LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_error_wakeup - connection initiating compare already failed"));
430: }
431: else
432: {
433: struct ds_bind_error * error = &(on->on_bind_compare->cn_start.cs_err);
434: switch(on->on_resp.di_error.de_err.dse_type)
435: {
436: case DSE_NOERROR:
437: LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_error_wakeup() - no error!"));
438: break;
439: case DSE_REFERRAL:
440: LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_error_wakeup() - DAP referral received!"));
441: case DSE_DSAREFERRAL:
442: /* Follow referral */
443: if(oper_rechain(on) == OK)
444: return;
445: break;
446: case DSE_NAMEERROR:
447: case DSE_SECURITYERROR:
448: case DSE_ATTRIBUTEERROR:
449: errtype = DBE_TYPE_SECURITY;
450: errmsg = DSE_SC_INVALIDCREDENTIALS;
451: break;
452: case DSE_SERVICEERROR:
453: errmsg = on->on_resp.di_error.de_err.ERR_SERVICE.DSE_sv_problem;
454: break;
455: default:
456: log_ds_error(&on->on_resp.di_error.de_err);
457: DLOG(log_dsap, LLOG_DEBUG, ("bind_compare_error_wakeup() - assuming all errors finish operation!"));
458: break;
459: }
460:
461: error->dbe_version = DBA_VERSION_V1988;
462: error->dbe_type = errtype;
463: error->dbe_value = errmsg;
464: conn_init_err(on->on_bind_compare);
465: }
466: oper_conn_extract(on);
467: oper_free(on);
468: }
469:
470: bind_compare_fail_wakeup(on)
471: struct oper_act * on;
472: {
473: DLOG(log_dsap, LLOG_TRACE, ("bind_compare_fail_wakeup()"));
474:
475: /*
476: * If there are any more "di_block"s to attempt it must be
477: * worth a go (perhaps this depends on the failure which
478: * has occurrred).
479: */
480: if(on->on_bind_compare == NULLCONN)
481: {
482: LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_fail_wakeup - connection initiating compare already failed"));
483: }
484: else
485: {
486: struct ds_bind_error * error = &(on->on_bind_compare->cn_start.cs_err);
487:
488: if(on->on_dsas)
489: {
490: if(oper_chain(on) == OK)
491: return;
492: }
493:
494: if(on->on_dsas)
495: {
496: /* oper_chain must be awaiting deferred di_blocks */
497: return;
498: }
499:
500: error->dbe_version = DBA_VERSION_V1988;
501: error->dbe_type = DBE_TYPE_SERVICE;
502: error->dbe_value = DSE_SV_UNAVAILABLE;
503: conn_init_err(on->on_bind_compare);
504: }
505: oper_conn_extract(on);
506: oper_free(on);
507: }
508:
509: do_ds_unbind (conn)
510: register struct connection * conn;
511: {
512: #ifndef NO_STATS
513: char buff[LINESIZE];
514:
515: if(conn->cn_initiator)
516: {
517: (void) sprintf (buff,"Unbind (%d) (initiator)",conn->cn_ad);
518: }
519: else
520: {
521: (void) sprintf (buff,"Unbind (%d) (responder)",conn->cn_ad);
522: }
523: pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)conn->cn_dn);
524: #endif
525: DLOG (log_dsap,LLOG_TRACE,("ds_un_bind"));
526: }
527:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.