static PE name2psap (DN dn) { int i; AttributeType at; PE pe; static struct ds_read_arg read_arg = { default_common_args, NULLDN, /* read_arg DN */ { /* entry info selection */ FALSE, NULLATTR, EIS_ATTRIBUTESANDVALUES } }; struct DSError error; struct ds_read_result result; if ((at = AttrT_new (DSAADDRESS_OID)) == NULLAttrT) { PY_advise (NULLCP, "build of attribute failed (%s)", DSAADDRESS_OID); return NULLPE; } read_arg.rda_common.ca_servicecontrol.svc_prio = SVC_PRIO_HIGH; read_arg.rda_object = dn; read_arg.rda_eis.eis_select = as_comp_new (AttrT_cpy (at), NULLAV, NULLACL_INFO); i = ds_read (&read_arg, &error, &result); AttrT_free (at); as_free (read_arg.rda_eis.eis_select); if (i != DS_OK) { PY_advise (NULLCP, "DAP lookup failed (%s)", dn2str (dn)); return NULLPE; } if (result.rdr_entry.ent_attr == NULLATTR) { PY_advise (NULLCP, "no '%s' attribute in entry '%s'", DSAADDRESS_OID, dn2str (dn)); return NULLPE; } pe = grab_pe (&result.rdr_entry.ent_attr -> attr_value -> avseq_av); as_free (result.rdr_entry.ent_attr); return pe; }
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) ; }
int call_modify (int argc, char **argv) { struct ds_modifyentry_arg mod_arg; struct DSError error; struct entrymod *emnew, *ems_append(), *modify_avs(); Attr_Sequence as, #ifdef TURBO_DISK fget_attributes (), #else get_attributes (), #endif temp, trail = NULLATTR; AV_Sequence avst = NULLAV; extern AttributeType at_objectclass; extern int parse_status; Entry entry_ptr; FILE *fd; char draft_flag = FALSE; char noedit_flag = FALSE; int x; DN moddn; char *home; RDN new_rdn; struct list_element *start = 0 ; struct list_element *last ; struct list_element *l_temp ; /* char add = FALSE ; char rem = FALSE ; */ if ((argc = service_control (OPT, argc, argv, &mod_arg.mea_common)) == -1) return; mod_arg.mea_changes = NULLMOD; new_draft = FALSE; if (home = getenv ("DISHDRAFT")) strcpy (fname, home); else if (dad_flag) { strcpy (fname, "/tmp/dishXXXXXX"); unlink (mktemp (fname)); } else if (home = getenv ("HOME")) sprintf (fname, "%s/.dishdraft", home); else strcpy (fname, "./.dishdraft"); for (x=1; x<argc; x++) { if (test_arg (argv[x], "-draft",1)) { draft_flag = 1; shuffle_up (argc--,argv,x); if (x == argc) { ps_printf (OPT, "Draft file name missing\n"); Usage (argv[0]); return; } strcpy (fname, argv[x]); shuffle_up (argc--,argv,x--); } else if (test_arg (argv[x], "-newdraft",2)) { new_draft = TRUE; shuffle_up (argc--,argv,x--); } else if (test_arg (argv[x], "-noedit",3)) { noedit_flag = TRUE; shuffle_up (argc--,argv,x--); } else if (move (argv[x]) == OK) shuffle_up (argc--,argv,x--); else if (test_arg(argv[x], "-remove", 3)) { shuffle_up (argc--, argv, x); if (x == argc) { ps_printf(OPT, "Attribute to remove missing\n") ; Usage(argv[0]) ; return ; } l_temp = (struct list_element *) malloc (sizeof(struct list_element)) ; l_temp->mod = (char *) malloc ((unsigned)(strlen(argv[x]) + 1)); strcpy (l_temp->mod, argv[x]) ; l_temp->add = 0 ; l_temp->next = 0 ; if (start == 0) { start = last = l_temp ; } else { last->next = l_temp ; last = l_temp ; } shuffle_up (argc--,argv,x--); } else if (test_arg(argv[x], "-add", 2)) { shuffle_up (argc--, argv, x); if (x == argc) { ps_printf(OPT, "Attribute to insert missing\n") ; Usage(argv[0]) ; return ; } l_temp = (struct list_element *) malloc (sizeof(struct list_element)) ; l_temp->mod = (char *) malloc ((unsigned)(strlen(argv[x]) + 1)); strcpy (l_temp->mod, argv[x]) ; l_temp->add = 1 ; l_temp->next = 0 ; if (start == 0) { start = last = l_temp ; } else { last->next = l_temp ; last = l_temp ; } shuffle_up (argc--,argv,x--); } } if (dad_flag && (draft_flag || noedit_flag)) { ps_printf (OPT, "operation not allowed when using directory assistance server!\n"); return; } /* read attributes we want to modify */ if ((argc = read_cache_aux (argc, argv, FALSE, &mod_arg.mea_common)) <0 ) return; if (argc != 1) { ps_printf (OPT,"Unknown option %s\n",argv[1]); Usage (argv[0]); return; } if (start != 0) { if (build_modify(start, &mod_arg) == NOTOK) { return ; } while (ds_modifyentry (&mod_arg, &error) != DS_OK) { if (dish_error (OPT, &error) == 0) { return ; } mod_arg.mea_object = 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 */ return ; } if (!draft_flag) { if (mod_template (fname,noedit_flag) != OK) return; noedit_flag = FALSE; } else { new_draft = TRUE; /* Ugh ! */ mod_template ("/dev/null",TRUE); } if (! noedit_flag) if (editentry (1, argv) != OK) { make_old (fname,draft_flag); return; } /* now parse the files */ if ((fd = fopen (fname, "r")) == (FILE *) NULL) { ps_printf (OPT, "Can't open draft entry %s\n", fname); return; } entry_ptr = get_default_entry (NULLENTRY); #ifdef TURBO_DISK entry_ptr->e_attributes = fget_attributes (fd); #else entry_ptr->e_attributes = get_attributes (fd); #endif fclose (fd); if (parse_status != 0) return; 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 */ for (new_rdn = entry_ptr->e_name; new_rdn != NULLRDN; new_rdn = new_rdn->rdn_next) { avst = avs_comp_new (AttrV_cpy (&new_rdn->rdn_av)); temp = as_comp_new (AttrT_cpy (new_rdn->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; } /* remove attribute missing in new entry */ for (as = current_entry->e_attributes; as != NULLATTR; as = as->attr_link) { emnew = NULLMOD; temp = entry_ptr->e_attributes; for (; temp != NULLATTR; temp = temp->attr_link) if (AttrT_cmp (as->attr_type, temp->attr_type) == 0) break; if (temp == NULLATTR) { emnew = em_alloc (); emnew->em_type = EM_REMOVEATTRIBUTE; emnew->em_what = as_comp_new(as->attr_type,NULLAV,NULLACL_INFO); emnew->em_next = NULLMOD; } if (emnew != NULLMOD) mod_arg.mea_changes = ems_append (mod_arg.mea_changes,emnew); } if (mod_arg.mea_changes == NULLMOD) { ps_print (RPS, "The draft entry and the entry for "); dn_print (RPS, dn, EDBOUT); ps_print (RPS, "\nare exactly the same - no change made!!!\n"); entry_free (entry_ptr); make_old (fname,draft_flag); return; } if (rebind () != OK) { entry_free (entry_ptr); return; } /* * If this operation is time-stamped, it may have expired while the user * was editing the entry. Re-calculate the time-stamp. Modify is the only * dish command where this needs to be done. */ if ((mod_arg.mea_common.ca_security != (struct security_parms *) 0) && (mod_arg.mea_common.ca_security->sp_time != NULLCP)) { char *new_version(); free(mod_arg.mea_common.ca_security->sp_time); mod_arg.mea_common.ca_security->sp_time = new_version(); } /* If security parameters are present, take this to mean that strong * authentication is required. This disallows 'parms + no signature' * (pointless) and 'signature + no parms' (security risk). */ if (mod_arg.mea_common.ca_security != (struct security_parms *) 0) { extern struct SecurityServices *dsap_security; mod_arg.mea_common.ca_sig = (dsap_security->serv_sign)((caddr_t)&mod_arg, _ZModifyEntryArgumentDataDAS, &_ZDAS_mod); } while (ds_modifyentry (&mod_arg, &error) != DS_OK) { if (dish_error (OPT, &error) == 0) { entry_free (entry_ptr); return; } mod_arg.mea_object = 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); make_old (fname,draft_flag); }
int do_ds_read (struct ds_read_arg *arg, struct DSError *error, struct ds_read_result *result, DN binddn, DN target, struct di_block **di_p, int dsp, int quipu_ctx, int authtype) { Entry entryptr; int retval; #ifdef NOTUSED int authenticated; #endif DN realtarget; char authp; DLOG (log_dsap,LLOG_TRACE,("ds_read")); if (!dsp) target = arg->rda_object; if (!dsp && dsa_read_control(arg,result)) return (DS_OK); if (target == NULLDN) { /* can't read from the root */ error->dse_type = DSE_NAMEERROR; error->ERR_NAME.DSE_na_problem = DSE_NA_NOSUCHOBJECT; error->ERR_NAME.DSE_na_matched = NULLDN; return (DS_ERROR_REMOTE); } switch(find_entry(target,&(arg->rda_common),binddn,NULLDNSEQ,FALSE,&(entryptr), error, di_p, OP_READ)) { case DS_OK: /* Filled out entryptr - carry on */ break; case DS_CONTINUE: /* Filled out di_p - what do we do with it ?? */ return(DS_CONTINUE); case DS_X500_ERROR: /* Filled out error - what do we do with it ?? */ return(DS_X500_ERROR); default: /* SCREAM */ LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_read() - find_entry failed")); return(DS_ERROR_LOCAL); } realtarget = get_copy_dn (entryptr); /* User can be authenticated by using strong authentication for this * operation, or by using the credntials from the bind. */ if (!manager(binddn)) authp = entryptr->e_authp ? entryptr->e_authp->ap_readandcompare : AP_SIMPLE; else authp = AP_SIMPLE; #ifdef NOTUSED authenticated = 0; /* Credentials provided in the ds_bind */ if ((bind_policy & POLICY_ACCESS_READ) && (!dsp) && (binddn != NULLDN)) authenticated = 1; #endif /* Strong authentication */ /* If it's there, check it, even if you won't believe it anyway */ if ((retval = check_security_parms((caddr_t) arg, _ZReadArgumentDataDAS, &_ZDAS_mod, arg->rda_common.ca_security, arg->rda_common.ca_sig, &binddn)) != 0) { error->dse_type = DSE_SECURITYERROR; error->ERR_SECURITY.DSE_sc_problem = retval; dn_free (realtarget); return (DS_ERROR_REMOTE); } #ifdef NOTUSED if ((strong_policy & POLICY_ACCESS_READ) && (arg->rda_common.ca_sig != (struct signature *) 0)) authenticated = 1; #endif /* entry has got a full list of attributes, eventually select one required */ if (check_acl ((authtype % 3) >= authp ? binddn : NULLDN, ACL_READ, entryptr->e_acl->ac_entry, realtarget) == NOTOK) { if (dsp && (check_acl (binddn,ACL_READ,entryptr->e_acl->ac_entry, realtarget) == OK)) { error->dse_type = DSE_SECURITYERROR; error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION; dn_free (realtarget); return (DS_ERROR_REMOTE); } else { error->dse_type = DSE_SECURITYERROR; error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS; dn_free (realtarget); return (DS_ERROR_REMOTE); } } if (entryptr->e_dsainfo && need_pseudo_dsa(entryptr,arg)) { /* Its a 7.0 or better DSA. * pseudo attributes asked for. * special routing req'd */ if (dn_cmp (realtarget, mydsadn) == 0) { /* Its me - generate result */ if ((result->rdr_entry.ent_attr = dsa_eis_select ( arg->rda_eis,entryptr, dsp ? NULLDN : binddn, quipu_ctx, realtarget)) != NULLATTR) goto out; if ( arg->rda_eis.eis_allattributes || arg->rda_eis.eis_select == NULLATTR) goto out; error->dse_type = DSE_ATTRIBUTEERROR; error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (entryptr); error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(arg->rda_eis.eis_select->attr_type); error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV; error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM; dn_free (realtarget); return (DS_ERROR_REMOTE); } else { /* make referral to DSA in this entry */ (*di_p) = di_alloc(); (*di_p)->di_type = DI_TASK; (*di_p)->di_dn = realtarget; (*di_p)->di_target = dn_cpy(realtarget); (*di_p)->di_reftype = RT_UNDEFINED; (*di_p)->di_rdn_resolved = CR_RDNRESOLVED_NOTDEFINED; (*di_p)->di_aliasedRDNs = CR_NOALIASEDRDNS; (*di_p)->di_entry = entryptr; entryptr->e_refcount++; (*di_p)->di_state = DI_COMPLETE; return DS_CONTINUE; } } if (cant_use_cache (entryptr,binddn,arg->rda_eis,realtarget)) { int res = referral_dsa_info(realtarget,NULLDNSEQ,FALSE,entryptr,error,di_p, arg->rda_common.ca_servicecontrol.svc_options & SVC_OPT_PREFERCHAIN); dn_free (realtarget); return res; } if (dsp && (eis_check (arg->rda_eis,entryptr, binddn) != OK)) { /* Can only send public things over DSP - but user is entitled to more */ error->dse_type = DSE_SECURITYERROR; error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION; dn_free (realtarget); return (DS_ERROR_REMOTE); } if ((result->rdr_entry.ent_attr = eis_select (arg->rda_eis,entryptr, dsp ? NULLDN : binddn, quipu_ctx, realtarget)) == NULLATTR) if ( !arg->rda_eis.eis_allattributes && arg->rda_eis.eis_select != NULLATTR) { error->dse_type = DSE_ATTRIBUTEERROR; error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (entryptr); error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE; error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(arg->rda_eis.eis_select->attr_type); error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV; error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM; dn_free (realtarget); return (DS_ERROR_REMOTE); } out: ; result->rdr_entry.ent_dn = realtarget; result->rdr_entry.ent_iscopy = entryptr->e_data; result->rdr_entry.ent_age = (time_t) 0; result->rdr_entry.ent_next = NULLENTRYINFO; result->rdr_common.cr_requestor = NULLDN; /* if no error and NOT SVC_OPT_DONTDEREFERENCEALIASES then */ /* the alias will have been derefeferenced -signified by */ /* NO_ERROR !!! */ result->rdr_common.cr_aliasdereferenced = (error->dse_type == DSE_NOERROR) ? FALSE : TRUE; return (DS_OK); }
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); } }