int task_abandon (struct task_act *tk) { struct oper_act * on; DLOG(log_dsap, LLOG_TRACE, ("task_abandon")); for(on = tk->tk_operlist; on != NULLOPER; on = on->on_next_task) { on->on_state = ON_ABANDONED; on->on_task = NULLTASK; if (on->on_dsas) { di_desist (on->on_dsas); on -> on_dsas = NULL_DI_BLOCK; } } ds_error_free (&tk->tk_resp.di_error.de_err); tk->tk_resp.di_error.de_err.dse_type = DSE_ABANDONED; task_error(tk); return(OK); }
dsEnqError list_start() { struct ds_search_arg search_arg; struct ds_search_result result; struct DSError error; dsEnqError return_error; return_error = Okay; if (get_default_service (&search_arg.sra_common) != 0) { return localdsaerror; } search_arg.sra_common.ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN; search_arg.sra_baseobject = (*base_path != 'T'? str2dn (base_path): NULLDN); search_arg.sra_eis.eis_allattributes = FALSE; search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTETYPESONLY; search_arg.sra_eis.eis_select = 0; search_arg.sra_searchaliases = TRUE; search_arg.sra_subset = SRA_ONELEVEL; search_arg.sra_filter = filter_alloc(); search_arg.sra_filter->flt_type = FILTER_NOT; search_arg.sra_filter->flt_next = NULLFILTER; search_arg.sra_filter->flt_un.flt_un_filter = filter_alloc(); search_arg.sra_filter->flt_un.flt_un_filter->flt_type = FILTER_ITEM; search_arg.sra_filter->flt_un.flt_un_filter->flt_next = NULLFILTER; search_arg.sra_filter->flt_un.flt_un_filter->flt_un.flt_un_item.fi_type = FILTERITEM_EQUALITY; search_arg.sra_filter->flt_un.flt_un_filter->flt_un.flt_un_item.fi_un. fi_un_ava.ava_type = AttrT_new("2.5.4.0"); search_arg.sra_filter->flt_un.flt_un_filter->flt_un.flt_un_item.fi_un. fi_un_ava.ava_value = str2AttrV("dsa", search_arg.sra_filter->flt_un.flt_un_filter-> flt_un.flt_un_item.fi_un.fi_un_ava.ava_type-> oa_syntax); #ifndef NO_STATS LLOG (log_stat,LLOG_NOTICE,("search +%s,extent %d, val objectClass != dsa", base_path,search_arg.sra_subset)); #endif if (search_arg.sra_filter->flt_un.flt_un_filter->flt_un.flt_un_item. fi_un.fi_un_ava.ava_value == NULLAttrV) { return_error = localdsaerror; } else if (ds_search (&search_arg, &error, &result) != DS_OK) { free_seq(dnseq); dnseq = NULLDS; dn_number = 0; log_ds_error(&error); ds_error_free(&error); switch (error.dse_type) { case DSE_LOCALERROR: return_error = duaerror; break; case DSE_REMOTEERROR: return_error = localdsaerror; break; case DSE_ATTRIBUTEERROR: return_error = attributerror; break; case DSE_REFERRAL: case DSE_DSAREFERRAL: return_error = remotedsaerror; break; case DSE_SECURITYERROR: return_error = security; break; case DSE_NAMEERROR: return_error = namerror; break; case DSE_SERVICEERROR: return_error = serviceerror; break; default: return_error = localdsaerror; break; } } else { dn_number = 0; if (result.CSR_entries != NULLENTRYINFO) { register EntryInfo *ptr; free_seq(dnseq); dnseq = NULLDS; dn_number = 0; for (ptr = result.CSR_entries; ptr != NULLENTRYINFO; ptr = ptr->ent_next) { dn_number++; dn2buf ((caddr_t)ptr->ent_dn, goto_path); add_seq (&dnseq, goto_path); } if (dn_number) dnseq = SortList(dnseq); } else if (result.CSR_limitproblem == LSR_NOLIMITPROBLEM) { free_seq(dnseq); dnseq = NULLDS; dn_number = 0; return_error = nothingfound; } if (result.CSR_limitproblem != LSR_NOLIMITPROBLEM) { switch (result.CSR_limitproblem) { case LSR_TIMELIMITEXCEEDED: if (dn_number > 0) return_error = timelimit_w_partial; else { free_seq(dnseq); dnseq = NULLDS; return_error = timelimit; } break; case LSR_SIZELIMITEXCEEDED: return_error = listsizelimit; break; case LSR_ADMINSIZEEXCEEDED: if (dn_number > 0) return_error = adminlimit_w_partial; else { free_seq(dnseq); dnseq = NULLDS; return_error = adminlimit; } break; } } if (result.CSR_entries) entryinfo_free(result.CSR_entries, 0); } entry_number = dn_number; filter_free(search_arg.sra_filter); dn_free(search_arg.sra_baseobject); ds_error_free(&error); return return_error; }
int really_find_entry ( DN object, int deref, struct dn_seq *dn_stack, int master, /* Generate only master references - NB does not imply returned entry is master */ Entry *ent_p, struct DSError *err, struct di_block **di_p ) { Entry parent; Avlnode *kids; int entryrdn_cmp (); RDN b_rdn; DN tdn, dn, dn_trail = NULLDN; DN aliasdn = NULLDN; int rdns, aliases; DLOG (log_dsap,LLOG_TRACE,("really find entry")); if (deref == -2) { /* alias loop */ err->dse_type = DSE_NAMEERROR; err->ERR_NAME.DSE_na_problem = DSE_NA_ALIASDEREFERENCE; err->ERR_NAME.DSE_na_matched = NULLDN; return (DS_X500_ERROR); } if (database_root == NULLENTRY) { LLOG (log_dsap,LLOG_NOTICE,("null root !!!")); return(dsa_info_parent(object, err, di_p, master)); } if ((dn = object) == NULLDN) { DLOG(log_dsap,LLOG_DEBUG,("really_fe - DS_OK: database_root")); (*ent_p) = database_root; return (DS_OK); } b_rdn = dn->dn_rdn; if ((kids = database_root->e_children) == NULLAVL) { DLOG(log_dsap, LLOG_DEBUG, ("database->e_child == NULLENTRY")); return (no_reply_child (object,dn,dn_stack,master,database_root,err,di_p)); } parent = database_root; for(rdns = 1, aliases = 0 ; ; rdns++ ) { /* break or return out */ *ent_p = (Entry) avl_find(kids, (caddr_t) b_rdn, entryrdn_cmp); if ( *ent_p == NULLENTRY ) { int res = no_reply_edb(object, dn_trail, dn_stack, master, parent, err, di_p); if (res == DS_CONTINUE) di_rdns (*di_p,rdns,aliases,NULLDN); if (aliasdn) dn_free (aliasdn); return res; } if ( (*ent_p)->e_alias != NULLDN ) /* got an alias entry */ if (deref != FALSE) { Entry new_entry; int new_deref; DN t_aliasdn; err->dse_type = DSE_NAMEERROR; new_deref = (deref == -1) ? -2 : -1; switch(really_find_entry ((*ent_p)->e_alias,new_deref,dn_stack,master,&(new_entry),err,di_p)) { case DS_OK: DLOG(log_dsap, LLOG_DEBUG, ("rfe:rfe:OK")); (*ent_p) = new_entry; t_aliasdn = aliasdn; aliasdn = get_copy_dn(new_entry); aliases = 0; for (tdn=aliasdn; tdn != NULLDN; tdn=tdn->dn_parent) aliases++; tdn = dn->dn_parent; if (aliasdn == NULLDN) dn = aliasdn = dn_cpy(tdn); else { for (dn = aliasdn; dn->dn_parent != NULLDN; dn = dn->dn_parent) ; dn->dn_parent = dn_cpy(tdn); } if (t_aliasdn) dn_free (t_aliasdn); object = aliasdn; break; case DS_CONTINUE: DLOG(log_dsap, LLOG_DEBUG, ("rfe:rfe:CONT")); #ifdef DEBUG di_list_log((*di_p)); #endif t_aliasdn = aliasdn; aliasdn = dn_cpy ((*ent_p)->e_alias); aliases = 0; for (tdn=aliasdn; tdn != NULLDN; tdn=tdn->dn_parent) aliases++; tdn = dn->dn_parent; if (aliasdn == NULLDN) dn = aliasdn = dn_cpy(tdn); else { for (dn = aliasdn; dn->dn_parent != NULLDN; dn = dn->dn_parent) ; dn->dn_parent = dn_cpy(tdn); } if (t_aliasdn) dn_free (t_aliasdn); di_rdns (*di_p,rdns,aliases,aliasdn); if (aliasdn) dn_free (aliasdn); return(DS_CONTINUE); case DS_X500_ERROR: DLOG(log_dsap, LLOG_DEBUG, ("rfe:rfe:X500ERR")); if ((err->dse_type == DSE_NAMEERROR) && ( err->ERR_NAME.DSE_na_problem == DSE_NA_ALIASDEREFERENCE)) { if (err->ERR_NAME.DSE_na_matched == NULLDN) { DN tmp_dn; tmp_dn = dn->dn_parent; dn->dn_parent = NULLDN; err->ERR_NAME.DSE_na_matched = dn_cpy(object); dn->dn_parent = tmp_dn; pslog (log_dsap,LLOG_EXCEPTIONS,"Alias deref Problem",(IFP)dn_print,(caddr_t)err->ERR_NAME.DSE_na_matched); } if (aliasdn) dn_free (aliasdn); return (DS_X500_ERROR); } else { ds_error_free (err); err->dse_type = DSE_NAMEERROR; err->ERR_NAME.DSE_na_problem = DSE_NA_ALIASPROBLEM; err->ERR_NAME.DSE_na_matched = dn_cpy((*ent_p)->e_alias); pslog (log_dsap,LLOG_EXCEPTIONS,"Alias Problem",(IFP)dn_print,(caddr_t)err->ERR_NAME.DSE_na_matched); if (aliasdn) dn_free (aliasdn); return (DS_X500_ERROR); } default: if (aliasdn) dn_free (aliasdn); DLOG(log_dsap, LLOG_DEBUG, ("rfe:rfe:localerror")); return(DS_ERROR_LOCAL); } } else if ( dn->dn_parent == NULLDN) { DLOG(log_dsap,LLOG_DEBUG,("really_fe - DS_OK: ?1")); if (aliasdn) dn_free (aliasdn); return(DS_OK); } else { /* alias on route - error in this case */ DN tmp_dn; err->dse_type = DSE_NAMEERROR; err->ERR_NAME.DSE_na_problem = DSE_NA_ALIASDEREFERENCE; tmp_dn = dn->dn_parent; dn->dn_parent = NULLDN; err->ERR_NAME.DSE_na_matched = dn_cpy(object); dn->dn_parent = tmp_dn; pslog (log_dsap,LLOG_EXCEPTIONS,"Alias deref(2) Problem",(IFP)dn_print,(caddr_t)err->ERR_NAME.DSE_na_matched); if (aliasdn) dn_free (aliasdn); return (DS_X500_ERROR); } if (dn->dn_parent == NULLDN) { DLOG(log_dsap,LLOG_DEBUG,("really_fe - DS_OK: ?2")); if (aliasdn) dn_free (aliasdn); return (DS_OK); } if ((*ent_p)->e_children == NULLAVL) { int res = no_reply_child (object,dn,dn_stack,master,(*ent_p),err,di_p); if (res == DS_CONTINUE) di_rdns (*di_p,rdns,aliases,NULLDN); if (aliasdn) dn_free (aliasdn); return res; } dn_trail = dn; dn = dn->dn_parent; b_rdn = dn->dn_rdn; kids = (*ent_p)->e_children; parent = *ent_p; } /* NOTREACHED */ }
int ds_bind_init (struct connection *cn) { struct ds_bind_arg * arg = &(cn->cn_start.cs_ds.ds_bind_arg); struct ds_bind_arg * result = &(cn->cn_start.cs_res); struct ds_bind_error * error = &(cn->cn_start.cs_err); Attr_Sequence as; Entry entryptr; extern AttributeType at_password; extern AttributeType at_p_password; struct di_block * dsas = NULL_DI_BLOCK; 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 extern struct SecurityServices *dsap_security; DLOG (log_dsap,LLOG_TRACE,("ds_bind_init")); if ( (arg->dba_version != DBA_VERSION_V1988) || quipu_shutdown) { 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_SERVICE; error->dbe_value = DSE_SV_UNAVAILABLE; 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; switch (arg->dba_auth_type) { case DBA_AUTH_NONE: if (((arg->dba_dn == NULLDN) && auth_bind == 1) || (auth_bind > 1)) { out: ; #ifndef NO_STATS if (arg->dba_dn == NULLDN) LLOG(log_stat, LLOG_TRACE, ("Bind (%d) (rejected)", cn->cn_ad)); else { sprintf (buff,"Bind (%d) (rejected)",cn->cn_ad); pslog (log_stat,LLOG_TRACE,buff,(IFP)dn_print, (caddr_t)arg->dba_dn); } #endif error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_AUTHENTICATION; return (DS_ERROR_CONNECT); } break; case DBA_AUTH_SIMPLE: if (auth_bind > 2) goto out; break; case DBA_AUTH_PROTECTED: if (auth_bind > 3) goto out; break; case DBA_AUTH_STRONG: break; case DBA_AUTH_EXTERNAL: goto out; } 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 */ if ( ! check_prefix_list (arg->dba_dn)) { #ifndef NO_STATS sprintf (buff,"Bind (%d) (reject - prefix)",cn->cn_ad); pslog (log_stat,LLOG_TRACE,buff,(IFP)dn_print, (caddr_t)arg->dba_dn); #endif error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_ACCESSRIGHTS; return (DS_ERROR_CONNECT); } if ((cn->cn_ctx == DS_CTX_X500_DAP) && !(check_dn_length(arg->dba_dn))) { #ifndef NO_STATS sprintf (buff,"Bind (%d) (reject - DAP length)",cn->cn_ad); pslog (log_stat,LLOG_TRACE,buff,(IFP)dn_print, (caddr_t)arg->dba_dn); #endif error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_ACCESSRIGHTS; return (DS_ERROR_CONNECT); } switch (arg->dba_auth_type) { case DBA_AUTH_NONE: /* partially check DN - i.e see if we can say if DEFINATELY does */ /* not exist. If it possibly exists - allow bind, checking it */ /* runs the risk of livelock */ switch (res = really_find_entry(arg->dba_dn, TRUE, NULLDNSEQ, FALSE, &(entryptr), &(err), &(dsas))) { case DS_X500_ERROR: if ((err.dse_type == DSE_NAMEERROR) && (err.ERR_NAME.DSE_na_problem == DSE_NA_NOSUCHOBJECT)) { ds_error_free(&(err)); #ifndef NO_STATS sprintf (buff,"Bind (%d) (no auth - rejected)",cn->cn_ad); pslog (log_stat,LLOG_TRACE,buff,(IFP)dn_print,(caddr_t)arg->dba_dn); #endif error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_INVALIDCREDENTIALS; return (DS_ERROR_CONNECT); } /* fall */ default: #ifndef NO_STATS sprintf (buff,"Bind (%d) (no auth)",cn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,(IFP)dn_print,(caddr_t)arg->dba_dn); #endif if (dsas != NULL_DI_BLOCK) di_desist (dsas); cn->cn_authen = DBA_AUTH_NONE; make_dsa_bind_arg(result); return (DS_OK); } case DBA_AUTH_SIMPLE: #ifndef NO_STATS sprintf (buff,"Bind (%d) (simple)",cn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,(IFP)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 != DS_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 sprintf (buff,"Bind (%d) (protected)",cn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,(IFP)dn_print,(caddr_t)arg->dba_dn); #endif if (cn->cn_ctx != DS_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(&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->is_protected[0] = (char) 1; } break; case DBA_AUTH_STRONG: #ifndef NO_STATS sprintf (buff,"Bind (%d) (strong)",cn->cn_ad); pslog (log_stat,LLOG_NOTICE,buff,(IFP)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 (dsap_security && dsap_security->serv_ckpath && dsap_security->serv_cknonce) { int rc; DN real_name; struct Nonce nonce; nonce.non_time1 = arg->dba_time1; nonce.non_time2 = arg->dba_time2; nonce.non_r1.n_bits = arg->dba_r1.n_bits; nonce.non_r1.value = arg->dba_r1.value; nonce.non_r2.n_bits = arg->dba_r2.n_bits; nonce.non_r2.value = arg->dba_r2.value; rc = (dsap_security->serv_cknonce)(&nonce); if (rc != OK) { error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = rc; return (DS_ERROR_CONNECT); } rc = (dsap_security->serv_ckpath)((caddr_t) arg, _ZTokenToSignDAS, &_ZDAS_mod, arg->dba_cpath, arg->dba_sig, &real_name); if (rc != OK) { error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = rc; return (DS_ERROR_CONNECT); } else { if(dn_cmp(real_name, arg->dba_dn) == OK) { make_dsa_bind_arg(result); return (DS_OK); } else { sprintf (buff,"User != Authenticated User, ie %s != ", dn2str(arg->dba_dn)); pslog (log_dsap,LLOG_NOTICE,buff,(IFP)dn_print,(caddr_t)real_name); error->dbe_version = DBA_VERSION_V1988; error->dbe_type = DBE_TYPE_SECURITY; error->dbe_value = DSE_SC_AUTHENTICATION; return (DS_ERROR_CONNECT); } } } else { if (cn->cn_ctx != DS_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_SERVICE; error->dbe_value = DSE_SV_UNAVAILABLE; 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_TRACE, ("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_start.cs_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 */ 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 */ if (on->on_req.dca_charg.cha_originator) /* set my set_my_chain_arg */ dn_free(on->on_req.dca_charg.cha_originator); 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_start.cs_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_TRACE, ("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); } if (arg->dba_auth_type == DBA_AUTH_SIMPLE) { if (strlen ((char *)as->attr_value->avseq_av.av_struct) != arg->dba_passwd_len) retval = -1; else 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); } }
int timeout_task (struct task_act *tk) { struct oper_act * on; struct DSError * err = &(tk->tk_resp.di_error.de_err); struct ds_search_task *tmp; DLOG(log_dsap, LLOG_TRACE, ("timeout_task")); for(on=tk->tk_operlist; on!=NULLOPER; on=on->on_next_task) { /* Time out operations started by task */ on->on_state = ON_ABANDONED; on->on_task = NULLTASK; if (on->on_dsas) { di_desist (on->on_dsas); on -> on_dsas = NULL_DI_BLOCK; } } if(tk->tk_dx.dx_arg.dca_dsarg.arg_type != OP_SEARCH) { ds_error_free (err); err->dse_type = DSE_SERVICEERROR; if (tk->tk_timed == TRUE) err->ERR_SERVICE.DSE_sv_problem = DSE_SV_TIMELIMITEXCEEDED; else /* tk->tk_timed == 2 */ err->ERR_SERVICE.DSE_sv_problem = DSE_SV_ADMINLIMITEXCEEDED; task_error(tk); task_extract(tk); } else { /* Do search collation */ if ((tk->tk_state == TK_ACTIVE) && (tk->local_st == NULL_ST)) { ds_error_free (err); /* nothing happened yet... */ err->dse_type = DSE_SERVICEERROR; if (tk->tk_timed == TRUE) err->ERR_SERVICE.DSE_sv_problem = DSE_SV_TIMELIMITEXCEEDED; else /* tk->tk_timed == 2 */ err->ERR_SERVICE.DSE_sv_problem = DSE_SV_ADMINLIMITEXCEEDED; task_error(tk); } else { /* send the results we have got... */ tk->tk_result = &(tk->tk_resp.di_result.dr_res); tk->tk_result->dcr_dsres.result_type = tk->tk_dx.dx_arg.dca_dsarg.arg_type; tk->tk_resp.di_type = DI_RESULT; if (tk->tk_timed == TRUE) tk->tk_resp.di_result.dr_res.dcr_dsres.res_sr.CSR_limitproblem = LSR_TIMELIMITEXCEEDED; else /* tk->tk_timed == 2 */ tk->tk_resp.di_result.dr_res.dcr_dsres.res_sr.CSR_limitproblem = LSR_ADMINSIZEEXCEEDED; /* Go through sub-tasks and add a POQ for each */ for(tmp=tk->referred_st; tmp!= NULL_ST; tmp=tmp->st_next) add_cref2poq (&tk->tk_result->dcr_dsres.res_sr,tmp->st_cr); task_result(tk); st_free_dis(&tk->referred_st,1); } task_extract(tk); } }
int oper_result (struct connection *cn, struct DSAPindication *di) { struct DSAPresult * dr = &(di->di_result); struct oper_act * on; DLOG(log_dsap, LLOG_TRACE, ("oper_result()")); for(on=cn->cn_operlist; on != NULLOPER; on=on->on_next_conn) { if(on->on_id == dr->dr_id) break; } if(on == NULLOPER) { LLOG(log_dsap, LLOG_FATAL, ("Cannot find operation to match result")); ds_res_free (&dr->dr_res.dcr_dsres); send_ro_ureject(cn->cn_ad, &(dr->dr_id), ROS_RRP_UNRECOG); return; } #ifndef NO_STATS LLOG(log_stat, LLOG_DEBUG, ("Result received (%d) [%d]", on->on_conn->cn_ad, on->on_id)); #endif if(on->on_state == ON_ABANDONED) { LLOG(log_dsap, LLOG_TRACE, ("oper_result - operation had been abandoned")); /* If we have the arguments we could do more caching here. */ if (dr->dr_res.dcr_dsres.result_type == OP_READ) cache_dsp_entry (&dr->dr_res.dcr_dsres.res_rd.rdr_entry); ds_res_free (&dr->dr_res.dcr_dsres); oper_extract(on); return; } if (dr->dr_res.dcr_dsres.result_type != on->on_arg->dca_dsarg.arg_type) { LLOG(log_dsap, LLOG_TRACE, ("oper_result - operation had been abandoned (2)")); send_ro_ureject(on->on_conn->cn_ad, &(dr->dr_id), ROS_RRP_MISTYPED); ds_res_free (&dr->dr_res.dcr_dsres); oper_extract(on); return; } /* free previous error - if any */ ds_error_free (&on->on_resp.di_error.de_err); on->on_resp = (*di); /* struct copy */ cn->cn_last_used = timenow; switch(on->on_type) { case ON_TYPE_X500: task_result_wakeup (on); break; case ON_TYPE_SUBTASK: subtask_result_wakeup (on); break; case ON_TYPE_BIND_COMPARE: bind_compare_result_wakeup(on); ds_res_free (&dr->dr_res.dcr_dsres); break; case ON_TYPE_GET_DSA_INFO: dsa_info_result_wakeup(on); ds_res_free (&dr->dr_res.dcr_dsres); break; case ON_TYPE_GET_EDB: case ON_TYPE_SHADOW: on->on_state = ON_COMPLETE; break; default: LLOG(log_dsap, LLOG_EXCEPTIONS, ("oper_result: operation of unknown type")); oper_extract(on); break; } }
dsEnqError srch_start() { struct ds_search_arg search_arg; struct ds_search_result result; struct DSError error; dsEnqError return_error; extern Filter make_filter(); DN curr_rdn; if (*mvalue == '\0') { return list_start(); } if (get_default_service (&search_arg.sra_common) != 0) { return nothingfound; } search_arg.sra_common.ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN; curr_rdn = search_arg.sra_baseobject = (*base_path != 'T'? str2dn (base_path): NULLDN); search_arg.sra_eis.eis_allattributes = FALSE; search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTETYPESONLY; search_arg.sra_eis.eis_select = 0; search_arg.sra_searchaliases = TRUE; search_arg.sra_subset = SRA_ONELEVEL; while (curr_rdn != NULLDN) { if (!strcmp(curr_rdn->dn_rdn->rdn_at->oa_ot.ot_stroid, "2.5.4.10")) { search_arg.sra_subset = SRA_WHOLESUBTREE; break; } curr_rdn = curr_rdn->dn_parent; } if ((search_arg.sra_filter = make_filter(filt_arr[typeindx])) == NULLFILTER) return duaerror; #ifndef NO_STATS LLOG (log_stat, LLOG_NOTICE, ("search +%s, extent %d, val %s", base_path,search_arg.sra_subset, mvalue)); #endif if(ds_search (&search_arg, &error, &result) != DS_OK) { /* deal with error */ free_seq(dnseq); dnseq = NULLDS; dn_number = 0; log_ds_error(&error); ds_error_free(&error); switch (error.dse_type) { case DSE_LOCALERROR: return_error = duaerror; break; case DSE_REMOTEERROR: return_error = localdsaerror; break; case DSE_ATTRIBUTEERROR: return_error = attributerror; break; case DSE_REFERRAL: case DSE_DSAREFERRAL: return_error = remotedsaerror; break; case DSE_SECURITYERROR: return_error = security; break; case DSE_NAMEERROR: return_error = namerror; break; case DSE_SERVICEERROR: return_error = serviceerror; break; default: return_error = localdsaerror; break; } } else { correlate_search_results (&result); dn_number = 0; if (result.CSR_entries != NULLENTRYINFO) { register EntryInfo *ptr; return_error = Okay; free_seq(dnseq); dnseq = NULLDS; dn_number = 0; for (ptr = result.CSR_entries; ptr != NULLENTRYINFO; ptr = ptr->ent_next){ dn_number++; dn2buf((caddr_t) ptr->ent_dn, goto_path); add_seq(&dnseq, goto_path); } if (dn_number) dnseq = SortList(dnseq); } else if (result.CSR_limitproblem == LSR_NOLIMITPROBLEM) { free_seq(dnseq); dnseq = NULLDS; dn_number = 0; return_error = nothingfound; } if(result.CSR_limitproblem != LSR_NOLIMITPROBLEM) { switch (result.CSR_limitproblem) { case LSR_TIMELIMITEXCEEDED: if (dn_number > 0) return_error = timelimit_w_partial; else { free_seq(dnseq); dnseq = NULLDS; return_error = timelimit; } break; case LSR_SIZELIMITEXCEEDED: return_error = listsizelimit; break; case LSR_ADMINSIZEEXCEEDED: if (dn_number > 0) return_error = adminlimit_w_partial; else { free_seq(dnseq); dnseq = NULLDS; return_error = adminlimit; } break; } entryinfo_free(result.CSR_entries, 0); } } entry_number = dn_number; filter_free(search_arg.sra_filter); dn_free(search_arg.sra_baseobject); ds_error_free(&error); return return_error; }
int task_chain (struct task_act *tk, struct di_block *di) { struct oper_act * on; struct DSError * err = &(tk->tk_resp.di_error.de_err); struct di_block * di_tmp; char refer_ok = TRUE; #ifdef DEBUG DLOG(log_dsap, LLOG_DEBUG, ("task_chain called with:")); di_list_log(di); #endif /* NB At some point this routine must assign the di_block list to * either the task (if it is intended to geneate a referral) or to * an operation hanging off that task if it is intended to chain the * task. This is fine when there are no deferred di_blocks, but when * there are then the information they will eventually contain is * needed to make a full decision on whether to chain or refer. * This needs a lot of thought to get right, for now the chain/refer * decision is made once and for all on the basis of the information * available now. Any information not available is assumed to force a * referral (the safe option - until network connectivity is considered)! * THis may introduce the unwelcome effect that a first request to a * DSA may produce a referral where subsequent requests do not - so much * for consistency but it won't happen that often if DSA info is cached * sensibly. */ /* * Generate the referral which the DSA will pass back if * chaining is disallowed or oper_chain fails for all * DSAs listed. */ sort_dsa_list (&di); if ((di_tmp = select_refer_dsa (di,tk)) == NULL_DI_BLOCK) { /* The remote END is probably unable to follow the referral - chain if allowed */ refer_ok = FALSE; for(di_tmp=di; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next) { if(di_tmp->di_state == DI_DEFERRED) continue; #ifdef DEBUG DLOG(log_dsap, LLOG_DEBUG, ("About to call di2cref with:")); di_log(di_tmp); #endif if(di2cref(di_tmp, err, tk->tk_conn->cn_ctx) == OK) break; } } else if (di2cref(di_tmp, err, tk->tk_conn->cn_ctx) != OK) di_tmp = NULL_DI_BLOCK; /* waiting... */ if(di_tmp == NULL_DI_BLOCK) { /* * Want to generate a referral - but all di_blocks (if any) * are deferred. Would we be lying too much if we said the * DSA was "busy" at this point??? */ ds_error_free (err); err->dse_type = DSE_SERVICEERROR; err->ERR_SERVICE.DSE_sv_problem = DSE_SV_BUSY; di_desist(di); return(NOTOK); } /* * If it would be inappropriate to chain this operation, then * generate a referral from the di_block list. */ if(chain_ok(tk,refer_ok,di_tmp->di_dn) == FALSE) { DLOG(log_dsap, LLOG_DEBUG, ("Referring!")); di_desist(di); return(NOTOK); } DLOG(log_dsap, LLOG_DEBUG, ("Chaining!")); /* Chain. Generate the new operation to send */ if((on = task2oper(tk)) == NULLOPER) { DLOG(log_dsap, LLOG_DEBUG, ("Why did task2oper fail??")); ds_error_free (err); err->dse_type = DSE_SERVICEERROR; err->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE; di_desist(di); return(NOTOK); } if(ti_is_elem(tk->tk_dx.dx_arg.dca_charg.cha_trace, tk->tk_dx.dx_arg.dca_charg.cha_trace->ti_next)) { DLOG (log_dsap,LLOG_TRACE,("Loop found in oper_chain()")); ds_error_free (err); err->dse_type = DSE_SERVICEERROR; err->ERR_SERVICE.DSE_sv_problem = DSE_SV_LOOPDETECT; return(NOTOK); } on->on_next_task = tk->tk_operlist; tk->tk_operlist = on; on->on_task = tk; /* Hand control of di_blocks to the operation */ on->on_dsas = di; for(di_tmp = di; 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) { oper_task_extract(on); oper_free(on); return(NOTOK); } #ifdef QUIPU_CONSOLE /* SPT trying to insert a chain_analyse here. */ /* The aim is to add this chained command to */ /* the open_call_avs structure */ chaining_analyse(tk, di) ; #endif /* QUIPU_CONSOLE */ return(OK); }