|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 14377 (0x3829) Types: TextFile Names: »ds_bind.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/quipu/ds_bind.c«
/* ds_bind.c - BindArgument Checking and Authentication */ #ifndef lint static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_bind.c,v 7.1 89/12/19 16:20:13 mrose Exp $"; #endif /* * $Header: /f/osi/quipu/RCS/ds_bind.c,v 7.1 89/12/19 16:20:13 mrose Exp $ * * * $Log: ds_bind.c,v $ * Revision 7.1 89/12/19 16:20:13 mrose * sync * * Revision 7.0 89/11/23 22:17:05 mrose * Release 6.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ #include "quipu/util.h" #include "quipu/entry.h" #include "quipu/commonarg.h" #include "quipu/bind.h" #include "quipu/compare.h" #include "quipu/dua.h" #include "quipu/connection.h" extern LLog * log_dsap; extern DN mydsadn; struct oper_act * oper_alloc(); #ifndef NO_STATS extern LLog * log_stat; extern int dn_print (); #endif int bind_window = 300; /* Tailorable timeout for credentials */ int ds_bind_init (cn) struct connection * cn; { struct ds_bind_arg * arg = &(cn->cn_init_act.ia_req); struct ds_bind_arg * result = &(cn->cn_init_act.ia_res); struct ds_bind_error * error = &(cn->cn_init_act.ia_err); Attr_Sequence as; Entry entryptr; extern AttributeType at_password; extern AttributeType at_p_password; struct di_block * dsas; struct di_block * di_tmp; struct oper_act * on; struct ds_compare_arg * cma; struct DSError err; static struct common_args ca_def = default_common_args; int res; int retval; struct protected_password * pp; #ifndef NO_STATS char buff[LINESIZE]; #endif DLOG (log_dsap,LLOG_TRACE,("ds_bind_init")); if (arg->dba_version != DBA_VERSION_V1988) { error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SERVICE; error->dbe_value = DSE_SV_UNAVAILABLE; return(DS_ERROR_CONNECT); } /* We don't support any bilaterally-defined authentication procedures. * Hence, if we get EXTERNAL credentials in the bind, reject them. */ if (arg->dba_auth_type == DBA_AUTH_EXTERNAL) { DLOG(log_dsap, LLOG_EXCEPTIONS, ("EXTERNAL found in credentials")); error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_AUTHENTICATION; return (DS_ERROR_CONNECT); } /* If password is present, but zero length, treat as though absent */ if ((arg->dba_auth_type == DBA_AUTH_SIMPLE) && (arg->dba_passwd_len == 0)) arg->dba_auth_type = DBA_AUTH_NONE; /* If binding as NULLDN (ie. `anonymous') don't need any authentication */ if (arg->dba_dn == NULLDN) { #ifndef NO_STATS LLOG(log_stat, LLOG_NOTICE, ("Bind (%d) (anonymous)", cn->cn_ad)); #endif cn->cn_authen = DBA_AUTH_NONE; make_dsa_bind_arg(result); return(DS_OK); } /* Now we're sure dba_dn contains a valid pointer, can decode it */ (void) dn_decode (arg->dba_dn); switch (arg->dba_auth_type) { case DBA_AUTH_NONE: #ifndef NO_STATS (void) sprintf (buff,"Bind (%d) (no auth)",cn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)arg->dba_dn); #endif cn->cn_authen = DBA_AUTH_NONE; make_dsa_bind_arg(result); return (DS_OK); case DBA_AUTH_SIMPLE: #ifndef NO_STATS (void) sprintf (buff,"Bind (%d) (simple)",cn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)arg->dba_dn); #endif /* Can't check simple credentials from DSP (livelock risk). * Hence treat DSP accesses as unauthenticated. */ if (cn->cn_ctx != CN_CTX_X500_DAP) { cn->cn_authen = DBA_AUTH_NONE; make_dsa_bind_arg(result); return(DS_OK); } break; case DBA_AUTH_PROTECTED: #ifndef NO_STATS (void) sprintf (buff,"Bind (%d) (protected)",cn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)arg->dba_dn); #endif if (cn->cn_ctx != CN_CTX_X500_DAP) { cn->cn_authen = DBA_AUTH_NONE; make_dsa_bind_arg(result); return(DS_OK); } else { UTC ut; long c_time, s_time, delta; time_t time(); (void) time(&s_time); ut = str2utct(arg->dba_time1, strlen(arg->dba_time1)); if (ut == NULLUTC) c_time = 0L; /* 1970 is a convenient out-of-date timestamp */ else c_time = gtime(ut2tm(ut)); delta = s_time - c_time; if ((delta < 0) || (delta > bind_window)) { DLOG(log_dsap, LLOG_EXCEPTIONS, ("Time = %s, Delay = %D s : Association rejected", arg->dba_time1, delta)); error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_INVALIDCREDENTIALS; return (DS_ERROR_CONNECT); } pp = (struct protected_password *) calloc(1, sizeof(*pp)); /* Ought to check for null pointer ... */ pp->passwd = malloc((unsigned)arg->dba_passwd_len); bcopy(arg->dba_passwd, pp->passwd, arg->dba_passwd_len); pp->n_octets = arg->dba_passwd_len; pp->time1 = strdup(arg->dba_time1); pp->protected = (char) 1; } break; case DBA_AUTH_STRONG: #ifndef NO_STATS (void) sprintf (buff,"Bind (%d) (strong)",cn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)arg->dba_dn); #endif /* Strong authentication is not yet supported. * It will eventually be possible to check strong credentials over DSP. * For the moment, accept them and treat as NONE over DSP, but reject * over DAP. */ if (cn->cn_ctx != CN_CTX_X500_DAP) { cn->cn_authen = DBA_AUTH_NONE; make_dsa_bind_arg(result); return (DS_OK); } else { error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_AUTHENTICATION; return (DS_ERROR_CONNECT); } } /* If we fall through to here, credentials are simple or protected simple */ if ((res = really_find_entry(arg->dba_dn, TRUE, NULLDNSEQ, FALSE, &(entryptr), &(err), &(dsas))) == DS_OK) { /* is it really OK ??? */ if ((entryptr->e_data == E_TYPE_CONSTRUCTOR) || (entryptr->e_data == E_TYPE_CACHE_FROM_MASTER)) { DN dn_found; DLOG(log_dsap, LLOG_NOTICE, ("rfe (bind) returned a constructor")); dn_found = get_copy_dn(entryptr); res = constructor_dsa_info(dn_found,NULLDNSEQ,FALSE,entryptr,&err,&dsas); dn_free (dn_found); } } switch(res) { case DS_OK: /* entryptr filled out - break through to deal with it */ break; case DS_CONTINUE: /* * At this point a remote operation is required to compare * the password given with the password of the entry, so * fire up the remote operation and return without completing. * Mark the operation as a BIND_COMPARE_OP and set the connection * which will need to be restarted. * Generate a compare argument. * Chain the compare operation using the di_blocks. */ cn->cn_bind_compare = on = oper_alloc(); /* cn knows about on */ on->on_type = ON_TYPE_BIND_COMPARE; on->on_bind_compare = cn; /* on knows about cn */ on->on_arg = &(on->on_req); set_my_chain_args(&(on->on_req.dca_charg), arg->dba_dn); on->on_req.dca_dsarg.arg_type = OP_COMPARE; cma = &(on->on_req.dca_dsarg.arg_cm); cma->cma_common = ca_def; /* struct copy */ /* Set originator/requestor */ on->on_req.dca_charg.cha_originator = dn_cpy(arg->dba_dn); cma->cma_common.ca_requestor = dn_cpy(arg->dba_dn); cma->cma_common.ca_servicecontrol.svc_prio = SVC_PRIO_HIGH; cma->cma_object = dn_cpy(arg->dba_dn); if (arg->dba_auth_type == DBA_AUTH_SIMPLE) { cma->cma_purported.ava_type = AttrT_cpy (at_password); cma->cma_purported.ava_value = str2AttrV (arg->dba_passwd,str2syntax("octetstring")); } else { cma->cma_purported.ava_type = AttrT_cpy (at_p_password); cma->cma_purported.ava_value = (AttributeValue) calloc(1, sizeof(attrVal)); cma->cma_purported.ava_value->av_syntax = str2syntax("protectedPassword"); cma->cma_purported.ava_value->av_struct = (caddr_t) pp; } on->on_dsas = dsas; for(di_tmp=on->on_dsas; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next) { di_tmp->di_type = DI_OPERATION; di_tmp->di_oper = on; } if(oper_chain(on) == OK) return(DS_CONTINUE); oper_extract(on); cn->cn_bind_compare = NULLOPER; error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SERVICE; error->dbe_value = DSE_SV_UNAVAILABLE; return(DS_ERROR_CONNECT); case DS_X500_ERROR: /* User's entry doesn't exist, for example */ LLOG(log_dsap, LLOG_NOTICE, ("ds_bind - really_find_entry erred:")); log_ds_error(&(err)); ds_error_free(&(err)); error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_INVALIDCREDENTIALS; return(DS_ERROR_CONNECT); default: error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SERVICE; error->dbe_value = DSE_SV_DITERROR; return(DS_ERROR_CONNECT); } if ((as = as_find_type (entryptr->e_attributes, (arg->dba_auth_type == DBA_AUTH_SIMPLE) ? at_password : at_p_password)) == NULLATTR) { /* No password in entry. * Simple authentication is not possible for entities without passwords. * Hence, give the `inappropriate authentication' message. */ error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_AUTHENTICATION; return (DS_ERROR_CONNECT); } /* Null terminate the password. Probably don't need this anymore, * but keep it in for safety. */ arg->dba_passwd[arg->dba_passwd_len] = '\0'; if (arg->dba_auth_type == DBA_AUTH_SIMPLE) retval = strncmp ((char *)as->attr_value->avseq_av.av_struct, arg->dba_passwd, arg->dba_passwd_len); else retval = check_guard( ((struct protected_password *) as->attr_value->avseq_av.av_struct)->passwd, ((struct protected_password *) as->attr_value->avseq_av.av_struct)->n_octets, arg->dba_time1, arg->dba_passwd, arg->dba_passwd_len); if (retval == 0) { /* Password OK! */ cn->cn_authen = arg->dba_auth_type; make_dsa_bind_arg(result); return (DS_OK); } else { /* password wrong ! */ error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_INVALIDCREDENTIALS; return (DS_ERROR_CONNECT); } } bind_compare_result_wakeup(on) struct oper_act * on; { DLOG(log_dsap, LLOG_TRACE, ("bind_compare_result_wakeup()")); if(on->on_bind_compare == NULLCONN) { LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_result_wakeup - connection initiating compare already failed")); } else { if(on->on_resp.resp_res.dcr_dsres.res_cm.cmr_matched) { DLOG(log_dsap, LLOG_DEBUG, ("bind_compare - user authenticated")); on->on_bind_compare->cn_authen = on->on_bind_compare->cn_init_act.ia_req.dba_auth_type; conn_init_res(on->on_bind_compare); } else { struct ds_bind_error * error = &(on->on_bind_compare->cn_init_act.ia_err); DLOG(log_dsap, LLOG_DEBUG, ("bind_compare - user NOT authenticated")); error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; /* Password match failed, therefore credentials are wrong */ error->dbe_value = DSE_SC_INVALIDCREDENTIALS; conn_init_err(on->on_bind_compare); } } oper_conn_extract(on); oper_free(on); } bind_compare_error_wakeup(on) struct oper_act * on; { int errmsg = DSE_SV_DITERROR; int errtype = DBE_TYPE_SERVICE; DLOG(log_dsap, LLOG_TRACE, ("bind_compare_error_wakeup()")); /* * Check for referral and rechain if appropriate; * Otherwise check if error requires propagation * or another of the original di_blocks to be chained to. */ if(on->on_bind_compare == NULLCONN) { LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_error_wakeup - connection initiating compare already failed")); } else { struct ds_bind_error * error = &(on->on_bind_compare->cn_init_act.ia_err); switch(on->on_resp.resp_err.dse_type) { case DSE_NOERROR: LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_error_wakeup() - no error!")); break; case DSE_REFERRAL: LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_error_wakeup() - DAP referral received!")); case DSE_DSAREFERRAL: /* Follow referral */ if(oper_rechain(on) == OK) return; break; case DSE_NAMEERROR: case DSE_SECURITYERROR: case DSE_ATTRIBUTEERROR: errtype = DBE_TYPE_SECURITY; errmsg = DSE_SC_AUTHENTICATION; break; case DSE_SERVICEERROR: errmsg = on->on_resp.resp_err.ERR_SERVICE.DSE_sv_problem; break; default: log_ds_error(&on->on_resp.resp_err); DLOG(log_dsap, LLOG_DEBUG, ("bind_compare_error_wakeup() - assuming all errors finish operation!")); break; } error->dbe_version = DBA_VERSION_V1988; error->dbe_type = errtype; error->dbe_value = errmsg; conn_init_err(on->on_bind_compare); } oper_conn_extract(on); oper_free(on); } bind_compare_fail_wakeup(on) struct oper_act * on; { DLOG(log_dsap, LLOG_TRACE, ("bind_compare_fail_wakeup()")); /* * If there are any more "di_block"s to attempt it must be * worth a go (perhaps this depends on the failure which * has occurrred). */ if(on->on_bind_compare == NULLCONN) { LLOG(log_dsap, LLOG_EXCEPTIONS, ("bind_compare_fail_wakeup - connection initiating compare already failed")); } else { struct ds_bind_error * error = &(on->on_bind_compare->cn_init_act.ia_err); if(on->on_dsas) { if(oper_chain(on) == OK) return; } if(on->on_dsas) { /* oper_chain must be awaiting deferred di_blocks */ return; } error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SERVICE; error->dbe_value = DSE_SV_UNAVAILABLE; conn_init_err(on->on_bind_compare); } oper_conn_extract(on); oper_free(on); } do_ds_unbind (conn) register struct connection * conn; { #ifndef NO_STATS char buff[LINESIZE]; if(conn->cn_initiator == INITIATED_BY_THIS) { (void) dn_decode (conn->cn_what); (void) sprintf (buff,"Unbind (%d) (by this)",conn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)conn->cn_what); } else { (void) dn_decode (conn->cn_who); (void) sprintf (buff,"Unbind (%d) (by that)",conn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,dn_print,(caddr_t)conn->cn_who); } #endif DLOG (log_dsap,LLOG_TRACE,("ds_un_bind")); } bind_arg_free (arg) struct ds_bind_arg *arg; { dn_free (arg->dba_dn); /* need to free ertificates etc */ }