main() { struct passwd *pw_entry ; struct passwd *getpwuid() ; struct stat buf ; int i = 1 ; int uid ; int um ; char pass1[LINESIZE] ; char pass2[LINESIZE] ; char Read_in_Stuff[LINESIZE] ; char **vecptr ; char *tmpdraft ; char home_dir[LINESIZE] ; char *p, *part1, *part2 ; char quipurc_file[100] ; char tailor_file[100] ; char user_name[9] ; char *localptr = Local ; char print_format = EDBOUT ; EntryInfo *ptr ; static CommonArgs ca = default_common_args; vecptr = (char **) malloc(100) ; vecptr[0] = malloc (LINESIZE) ; (void) strcpy(vecptr[0], "showentry") ; (void) strcpy(pass1, "x") ; (void) strcpy(pass2, "y") ; tmpdraft = malloc (LINESIZE) ; (void) strcpy(tmpdraft, "/tmp/dish-") ; if ((opt = ps_alloc (std_open)) == NULLPS) fatal (-62, "ps_alloc failed"); if (std_setup (opt, stderr) == NOTOK) fatal (-63, "std_setup failed"); if ((rps = ps_alloc (std_open)) == NULLPS) fatal (-64, "ps_alloc 2 failed"); if (std_setup (rps, stdout) == NOTOK) fatal (-65, "std_setup 2 failed"); (void) strcpy(filterstring, "userid=") ; /* Sort out files, userids etc. */ uid=getuid() ; if ((pw_entry=getpwuid(uid)) == 0) { ps_printf(rps, "Who are you? (no name for your uid number)\n") ; exit(1) ; } (void) strcpy(user_name, pw_entry->pw_name) ; (void) strcat(tmpdraft, user_name) ; if (getenv("HOME") == 0) { ps_printf(rps, "No home directory?!!") ; (void) strcpy(home_dir, pw_entry->pw_dir) ; } else { (void) strcpy(home_dir, getenv("HOME")) ; } (void) strcpy(quipurc_file, home_dir) ; (void) strcat(quipurc_file, "/.quipurc") ; (void) strcpy(tailor_file, isodefile ("dishinit", 1)); Manager[0] = 0; Password[0] = 0; Local[0] = 0; (void) stat(tailor_file, &buf) ; (void) seteuid(buf.st_uid) ; /* set effective to enable */ /* us to read protected file */ if ((fp_tailor = fopen(tailor_file, "r")) == 0) { ps_print(rps, "Can't open Tailor File. Abort.\n") ; exit(1) ; } while (fgets (Read_in_Stuff, LINESIZE, fp_tailor) != 0) { if (!strcmp(Read_in_Stuff, "##Anything after this line is copied into the users ~/.quipurc file\n")) { break ; } p = SkipSpace (Read_in_Stuff); if (( *p == '#') || (*p == '\0')) continue; /* ignore comments and blanks */ part1 = p; if ((part2 = index (p,':')) == NULLCP) { ps_printf (opt,"Seperator missing '%s'. Ignoring..\n",p); } *part2++ = '\0'; part2 = TidyString (part2); if (lexequ(part1, "manager") == 0) { (void) strcpy(Manager, part2) ; } else if (lexequ(part1, "password") == 0) { (void) strcpy(Password, part2) ; } else if (lexequ(part1, "local") == 0) { (void) strcpy(Local, part2) ; } else { ps_printf(rps, "Error in tailor. What's a %s?\n", part1) ; } } (void) setuid(uid) ; /* Restore Userid to original user. */ /* create ~/.quipurc file. NB this does eradicate anything in there. * (Theoretically nothing.) */ if (Manager[0] == 0) { ps_print(rps, "Can't find out the managers name\n") ; exit(1) ; } if (Password[0] == 0) { ps_print(rps, "Can't find out the managers password\n") ; exit(1) ; } if (Local[0] == 0) { ps_print(rps, "Can't find out where to search\n") ; exit(1) ; } um = umask(0177) ; if ((fp_quipurc = fopen(quipurc_file, "w")) == 0) { ps_printf(rps, "Can't open ~/.quipurc. Aborting..\n") ; exit(1) ; } (void) umask(um) ; if ((fileps = ps_alloc(std_open)) == NULLPS) { fatal (-66, "ps_alloc 2 failed"); } if (std_setup (fileps, fp_quipurc) == NOTOK) { fatal (-67, "std_setup 2 failed"); } /* Sorting out the bind section */ quipu_syntaxes() ; /* set up the needed function pointers */ dsap_init(&i, &vecptr) ; (void) strcpy(bindarg.dba_passwd, Password) ; bindarg.dba_version = DBA_VERSION_V1988; bindarg.dba_passwd_len = strlen(bindarg.dba_passwd) ; if ((bindarg.dba_dn = str2dn (Manager)) == NULLDN) { ps_printf (opt,"Invalid Manager name %s (???!)\n",Manager) ; exit(1) ; } if (ds_bind (&bindarg, &binderr, &bindresult) != OK) { ps_printf(rps, "Can't bind as the manager.\n") ; exit(1); } /* Hopefully, should be successfully bound */ /* * We now call the search stuff with the right bits, to see if we can get a * match of uid='user_name'. Once there, we echo lots of information from * their entry out to the .quipurc file. * Hopefully there should only be one match. This assumes that ALL dir info * up to date, and that SG do not allow multiple users with the same login. */ /* set up the appropriate structures and defaults. */ search_arg.sra_common = ca; /* struct copy */ search_arg.sra_common.ca_servicecontrol.svc_sizelimit = 2 ; search_arg.sra_eis.eis_allattributes = FALSE ; search_arg.sra_searchaliases = FALSE; search_arg.sra_subset = SRA_ONELEVEL; search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES ; search_arg.sra_eis.eis_select = NULLATTR ; search_arg.sra_eis.eis_allattributes = TRUE ; search_arg.sra_filter = filter_alloc() ; /* Default filter. */ search_arg.sra_filter->flt_next = NULLFILTER; search_arg.sra_filter->flt_type = FILTER_ITEM; search_arg.sra_filter->FUFILT = NULLFILTER; if (*localptr == '@') { localptr++; } if ((search_arg.sra_baseobject = str2dn(localptr)) == NULLDN) { ps_printf (opt,"Invalid sequence in username %s.\n", localptr); exit(1) ; } (void) strcat(filterstring, user_name) ; search_arg.sra_filter->flt_un.flt_un_item.fi_type = FILTERITEM_EQUALITY ; if ((search_arg.sra_filter->flt_un.flt_un_item.fi_un.fi_un_ava.ava_type = AttrT_new ("userid")) == NULLAttrT) { ps_printf(rps, "Oops, userid is not a valid attr type. ABORT!!\n") ; exit(1) ; } if ((search_arg.sra_filter->flt_un.flt_un_item.fi_un.fi_un_ava.ava_value = str2AttrV (user_name, search_arg.sra_filter->flt_un.flt_un_item.fi_un.fi_un_ava.ava_type->oa_syntax)) == NULLAttrV) { ps_printf(rps, "%s is not a valid attribute value.\n", user_name) ; } /* call search */ /* We now ought to be in the right place, and with the search stuff set, * ready to call search, and receive one (or no) entry back, which then * gets processed accordingly. */ if (ds_search (&search_arg, &search_error, &search_result) != DS_OK) { ps_printf(rps, "Search failed...\n") ; exit (1) ; /* This is not the same as coming back with */ /* message "search failed to find anything. */ } /* If the user does not exist in the DIT, print out the limited .quipurc * and the warning message, and allow the user to play DISH. */ if (search_result.CSR_entries == NULLENTRYINFO) { ps_printf(opt, "Unfortunately, you seem to have no entry in\n") ; ps_printf(opt, "the directory. Contact '%s' who should be able to help.\n", Manager) ; ps_printf(opt, "In the mean time, you can read, but not write.\n") ; } else { ptr = search_result.CSR_entries ; dn = dn_cpy(ptr->ent_dn) ; /* Essence of move user_name. */ /* collect the info and put it into current_entry */ /* Set up the desired attribute type to be read*/ /* from read.c */ if ((at = AttrT_new ("userPassword")) != NULLAttrT) { as_flag = as_merge (as_flag, as_comp_new (AttrT_cpy (at), NULLAV, NULLACL_INFO)); } else { ps_printf(rps, "Oops, Serious error. unknown attribute type 'userPassword'.\n") ; exit(1) ; } if ((current_entry = local_find_entry (dn, FALSE)) == NULLENTRY) { read_arg.rda_common = ca; /* struct copy */ read_arg.rda_object = dn; read_arg.rda_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; read_arg.rda_eis.eis_allattributes = TRUE ; read_arg.rda_eis.eis_select = NULLATTR ; if (ds_read (&read_arg, &read_error, &read_result) != DS_OK) { ps_printf(rps, "We even seem to be having problems reading\n" ) ; ps_printf(rps, "an entry we searched and found!! HELP!!\n") ; exit(1) ; } if (read_result.rdr_entry.ent_attr == NULLATTR) { ps_printf(rps, "No attributes present. Even though\n") ; ps_printf(rps, "we found you by userid attribute!!! HELP!!\n") ; exit (1) ; } cache_entry (&(read_result.rdr_entry), read_arg.rda_eis.eis_allattributes, TRUE) ; } if ((current_entry = local_find_entry (dn, FALSE)) == NULLENTRY) { ps_printf(rps, "We still have nothing.Even after reading? Abort.\n") ; exit(1) ; } ps_printf(fileps, "username: "******"\n") ; ps_printf(fileps, "me: ") ; dn_print(fileps, dn, EDBOUT) ; ps_printf(fileps, "\n") ; /* now showattribute -nokey to display it. */ ps_printf(fileps, "password: "******"You need a password...\n") ; (void) strcpy(pass1, getpassword("Enter Password: "******"Re-enter password: "******"\nMismatch - Try again.\n") ; } } ps_printf(fileps, "%s\n", pass1) ; um = umask(0177) ; if ((fp_draft = fopen(tmpdraft, "w")) == 0) { ps_print(rps, "Can't open draft file... Abort.\n") ; exit(1) ; } (void) umask(um) ; (void) fprintf(fp_draft, "UserPassword = %s\n", pass1) ; (void) fprintf(fp_draft, "acl = self # write # attributes # acl $ userPassword\n") ; (void) fprintf(fp_draft, "acl = others # compare # attributes # acl $ userPassword\n\n") ; (void) fclose(fp_draft) ; if ((fp_draft = fopen (tmpdraft, "r")) == NULL) { ps_printf (opt, "Can't open draft entry %s\n", tmpdraft); exit(1) ; } entry_ptr = get_default_entry (NULLENTRY); #ifdef TURBO_DISK entry_ptr->e_attributes = fget_attributes (fp_draft); #else entry_ptr->e_attributes = get_attributes (fp_draft); #endif (void) fclose (fp_draft); mod_arg.mea_common = ca; /* struct copy */ mod_arg.mea_object = dn; for (moddn = dn ; moddn->dn_parent != NULLDN; moddn=moddn->dn_parent) ; entry_ptr->e_name = rdn_cpy (moddn->dn_rdn); /* add rdn as attribute */ avst = avs_comp_new (AttrV_cpy (&entry_ptr->e_name->rdn_av)); temp = as_comp_new (AttrT_cpy (entry_ptr->e_name->rdn_at), avst, NULLACL_INFO); entry_ptr->e_attributes = as_merge (entry_ptr->e_attributes, temp); for (as = entry_ptr->e_attributes; as != NULLATTR; as = as->attr_link) { emnew = NULLMOD; trail = as->attr_link; as->attr_link = NULLATTR; temp = current_entry->e_attributes; for (; temp != NULLATTR; temp = temp->attr_link) if (AttrT_cmp (as->attr_type, temp->attr_type) == 0) { /* found it - does it need changing ? */ if (avs_cmp (as->attr_value, temp->attr_value) != 0) emnew = modify_avs (as->attr_value, temp->attr_value,as->attr_type); break; } if (temp == NULLATTR) { emnew = em_alloc (); emnew->em_type = EM_ADDATTRIBUTE; emnew->em_what = as_cpy(as); emnew->em_next = NULLMOD; } if (emnew != NULLMOD) { mod_arg.mea_changes = ems_append (mod_arg.mea_changes,emnew); } as->attr_link = trail; } while (ds_modifyentry (&mod_arg, &mod_error) != DS_OK) { if (dish_error (opt, &mod_error) == 0) { ps_printf(rps,"We have a dish error. Bye.\n") ; entry_free (entry_ptr); exit(1) ; } mod_arg.mea_object = mod_error.ERR_REFERRAL.DSE_ref_candidates->cr_name; } ps_print (rps, "Modified "); dn_print (rps, dn, EDBOUT); ps_print (rps, "\n"); delete_cache (dn); /* re-cache when next read */ entry_free (entry_ptr); ems_part_free (mod_arg.mea_changes); } } while(fgets(Read_in_Stuff, LINESIZE, fp_tailor) != 0) { fputs(Read_in_Stuff, fp_quipurc) ; } (void) fclose(fp_quipurc) ; (void) fclose(fp_tailor) ; /* (void) fprintf(fp_quipurc, "dsap: local_dit \"%s\"\n", Local) ; (void) fprintf(fp_quipurc, "notype: acl\n") ; (void) fprintf(fp_quipurc, "notype: treestructure\n") ; (void) fprintf(fp_quipurc, "notype: masterdsa\n") ; (void) fprintf(fp_quipurc, "notype: slavedsa\n") ; (void) fprintf(fp_quipurc, "notype: objectclass\n") ; (void) fprintf(fp_quipurc, "cache_time: 30\n") ; (void) fprintf(fp_quipurc, "connect_time: 2\n") ; */ (void) ds_unbind() ; (void) unlink(tmpdraft) ; }
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 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); } }