|
|
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.