static int nisplus_search_callback(const nis_name key, const nis_object *value, voidp opaquedata) { struct nisplus_search_callback_data *data = (struct nisplus_search_callback_data *) opaquedata; dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0)); dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1)); data->value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1)); return TRUE; }
static int nisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata) { char *kp = strnsave(ENTRY_VAL(value, 0), ENTRY_LEN(value, 0)); char *vp = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1)); struct nis_callback_data *data = (struct nis_callback_data *) opaquedata; dlog("NISplus callback for <%s,%s>", kp, vp); (*data->ncd_fn) (data->ncd_m, kp, vp); /* * We want more ... */ return FALSE; }
/* Check that someone else don't have the same auth information already */ static nis_error auth_exists(char *princname, char *auth_name, char *auth_type, char *domain) { char sname[NIS_MAXNAMELEN+MAXHOSTNAMELEN+64]; nis_result *res; nis_error status; char *foundprinc; (void) sprintf(sname, "[auth_name=%s,auth_type=%s],%s.%s", auth_name, auth_type, CRED_TABLE, domain); if (sname[strlen(sname)-1] != '.') strcat(sname, "."); /* Don't want FOLLOW_PATH here */ res = nis_list(sname, MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS, NULL, NULL); status = res->status; switch (res->status) { case NIS_NOTFOUND: break; case NIS_TRYAGAIN : (void) fprintf(stderr, "%s: NIS+ server busy, try again later.\n", program_name); exit(1); case NIS_PERMISSION : (void) fprintf(stderr, "%s: insufficient permission to look up old credentials.\n", program_name); exit(1); case NIS_SUCCESS: foundprinc = ENTRY_VAL(res->objects.objects_val, 0); if (nis_dir_cmp(foundprinc, princname) != SAME_NAME) { (void) fprintf(stderr, "%s: %s credentials with auth_name '%s' already belong to '%s'.\n", program_name, auth_type, auth_name, foundprinc); exit(1); } break; default: (void) fprintf(stderr, "%s: error looking at cred table, NIS+ error: %s\n", program_name, nis_sperrno(res->status)); exit(1); } nis_freeresult(res); return (status); }
nis_name nis_local_principal (void) { static char __principal[NIS_MAXNAMELEN + 1]; if (__principal[0] == '\0') { char buf[NIS_MAXNAMELEN + 1]; nis_result *res; uid_t uid = geteuid (); if (uid != 0) { int len = snprintf (buf, NIS_MAXNAMELEN - 1, "[auth_name=%d,auth_type=LOCAL],cred.org_dir.%s", uid, nis_local_directory ()); if (len >= NIS_MAXNAMELEN - 1) nobody: /* XXX The buffer is too small. Can this happen??? */ return strcpy (__principal, "nobody"); if (buf[len - 1] != '.') { buf[len++] = '.'; buf[len] = '\0'; } res = nis_list (buf, USE_DGRAM + NO_AUTHINFO + FOLLOW_LINKS + FOLLOW_PATH, NULL, NULL); if (res == NULL) goto nobody; if (NIS_RES_STATUS (res) == NIS_SUCCESS) { if (res->objects.objects_len > 1) { /* More than one principal with same uid? something wrong with cred table. Should be unique. Warn user and continue. */ printf (_("\ LOCAL entry for UID %d in directory %s not unique\n"), uid, nis_local_directory ()); } strcpy (__principal, ENTRY_VAL (res->objects.objects_val, 0)); nis_freeresult (res); return __principal; }
/************************************************************************* gets a NIS+ attribute *************************************************************************/ static void get_single_attribute(nis_object *new_obj, int col, char *val, int len) { int entry_len; if (new_obj == NULL || val == NULL) return; entry_len = ENTRY_LEN(new_obj, col); if (len > entry_len) { len = entry_len; } safe_strcpy(val, ENTRY_VAL(new_obj, col), len-1); }
/* * Try to locate a key using NIS+. */ int nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp) { nis_result *result; int error = 0; struct nisplus_search_callback_data data; nis_name index; char *org; /* if map does not have ".org_dir" then append it */ size_t l; org = strstr(map, NISPLUS_ORGDIR); if (org == NULL) org = NISPLUS_ORGDIR; else org = ""; /* make some room for the NIS index */ l = sizeof('[') /* for opening selection criteria */ + sizeof(NISPLUS_KEY) + strlen(key) + sizeof(']') /* for closing selection criteria */ + sizeof(',') /* + 1 for , separator */ + strlen(map) + sizeof(NISPLUS_ORGDIR); index = xmalloc(l); if (index == NULL) { plog(XLOG_ERROR, "Unable to create index %s: %s", map, strerror(ENOMEM)); return ENOMEM; } xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org); data.key = key; data.value = NULL; dlog("NISplus search for %s", index); result = nis_list(index, EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH, (int (*)()) nisplus_search_callback, &data); /* free off the NIS index */ XFREE(index); if (result == NULL) { plog(XLOG_ERROR, "nisplus_search: %s: %s", map, strerror(ENOMEM)); return ENOMEM; } /* * Do something interesting with the return code */ switch (result->status) { case NIS_SUCCESS: case NIS_CBRESULTS: if (data.value == NULL) { nis_object *value = result->objects.objects_val; dlog("NISplus search found <nothing>"); dlog("NISplus search for %s: %s(%d)", map, nis_sperrno(result->status), result->status); if (value != NULL) data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1)); } if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) { *val = sun_entry2amd(key, data.value); XFREE(data.value); /* strnsave malloc'ed it above */ } else *val = data.value; if (*val) { error = 0; dlog("NISplus search found %s", *val); } else { error = ENOENT; dlog("NISplus search found nothing"); } *tp = 0; break; case NIS_NOSUCHNAME: dlog("NISplus search returned %d", result->status); error = ENOENT; break; default: plog(XLOG_ERROR, "nisplus_search: %s: %s", map, nis_sperrno(result->status)); error = EIO; break; } nis_freeresult(result); return error; }
/************************************************************************ makes a struct sam_passwd from a NIS+ object. ************************************************************************/ static BOOL make_sam_from_nisp_object(SAM_ACCOUNT *pw_buf, nis_object *obj) { char *ptr; pstring full_name; /* this must be translated to dos code page */ pstring acct_desc; /* this must be translated to dos code page */ pstring home_dir; /* set default value from smb.conf for user */ pstring home_drive; /* set default value from smb.conf for user */ pstring logon_script; /* set default value from smb.conf for user */ pstring profile_path; /* set default value from smb.conf for user */ pstring hours; int hours_len; unsigned char smbpwd[16]; unsigned char smbntpwd[16]; /* * time values. note: this code assumes 32bit time_t! */ pdb_set_logon_time(pw_buf, (time_t)0); ptr = ENTRY_VAL(obj, NPF_LOGON_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "LNT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_logon_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_logoff_time(pw_buf, get_time_t_max()); ptr = ENTRY_VAL(obj, NPF_LOGOFF_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "LOT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_logoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_kickoff_time(pw_buf, get_time_t_max()); ptr = ENTRY_VAL(obj, NPF_KICK_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "KOT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_kickoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_pass_last_set_time(pw_buf, (time_t)0); ptr = ENTRY_VAL(obj, NPF_PWDLSET_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "LCT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_pass_last_set_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_pass_can_change_time(pw_buf, (time_t)0); ptr = ENTRY_VAL(obj, NPF_PWDCCHG_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "CCT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_pass_can_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } pdb_set_pass_must_change_time(pw_buf, get_time_t_max()); /* Password never expires. */ ptr = ENTRY_VAL(obj, NPF_PWDMCHG_T); if(ptr && *ptr && (StrnCaseCmp(ptr, "MCT-", 4)==0)) { int i; ptr += 4; for(i = 0; i < 8; i++) { if(ptr[i] == '\0' || !isxdigit(ptr[i])) break; } if(i == 8) { pdb_set_pass_must_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } } /* string values */ pdb_set_username(pw_buf, ENTRY_VAL(obj, NPF_NAME)); pdb_set_domain(pw_buf, lp_workgroup()); /* pdb_set_nt_username() -- cant set it here... */ get_single_attribute(obj, NPF_FULL_NAME, full_name, sizeof(pstring)); unix_to_dos(full_name); pdb_set_fullname(pw_buf, full_name); pdb_set_acct_ctrl(pw_buf, pdb_decode_acct_ctrl(ENTRY_VAL(obj, NPF_ACB))); get_single_attribute(obj, NPF_ACCT_DESC, acct_desc, sizeof(pstring)); unix_to_dos(acct_desc); pdb_set_acct_desc(pw_buf, acct_desc); pdb_set_workstations(pw_buf, ENTRY_VAL(obj, NPF_WORKSTATIONS)); pdb_set_munged_dial(pw_buf, NULL); /* Might want to consult sys_getpwnam for the following two. for now, use same default as pdb_fill-default_sam */ ptr = ENTRY_VAL(obj, NPF_UID); pdb_set_uid(pw_buf, ptr ? atoi(ptr) : -1); ptr = ENTRY_VAL(obj, NPF_SMB_GRPID); pdb_set_gid(pw_buf, ptr ? atoi(ptr) : -1); ptr = ENTRY_VAL(obj, NPF_USER_RID); pdb_set_user_rid(pw_buf, ptr ? atoi(ptr) : pdb_uid_to_user_rid(pdb_get_uid(pw_buf))); ptr = ENTRY_VAL(obj, NPF_GROUP_RID); pdb_set_group_rid(pw_buf, ptr ? atoi(ptr) : pdb_gid_to_group_rid(pdb_get_gid(pw_buf))); /* values, must exist for user */ if( !(pdb_get_acct_ctrl(pw_buf) & ACB_WSTRUST) ) { /* FIXME!! This doesn't belong here. Should be set in net_sam_logon() --jerry */ pstrcpy(samlogon_user, pdb_get_username(pw_buf)); get_single_attribute(obj, NPF_HOME_DIR, home_dir, sizeof(pstring)); if( !(home_dir && *home_dir) ) { pstrcpy(home_dir, lp_logon_home()); pdb_set_homedir(pw_buf, home_dir, False); } else pdb_set_homedir(pw_buf, home_dir, True); get_single_attribute(obj, NPF_DIR_DRIVE, home_drive, sizeof(pstring)); if( !(home_drive && *home_drive) ) { pstrcpy(home_drive, lp_logon_drive()); pdb_set_dir_drive(pw_buf, home_drive, False); } else pdb_set_dir_drive(pw_buf, home_drive, True); get_single_attribute(obj, NPF_LOGON_SCRIPT, logon_script, sizeof(pstring)); if( !(logon_script && *logon_script) ) { pstrcpy(logon_script, lp_logon_script()); pdb_set_logon_script(pw_buf, logon_script, False); } else pdb_set_logon_script(pw_buf, logon_script, True); get_single_attribute(obj, NPF_PROFILE_PATH, profile_path, sizeof(pstring)); if( !(profile_path && *profile_path) ) { pstrcpy(profile_path, lp_logon_path()); pdb_set_profile_path(pw_buf, profile_path, False); } else pdb_set_profile_path(pw_buf, profile_path, True); } else { /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ pdb_set_group_rid (pw_buf, DOMAIN_GROUP_RID_USERS); } /* Check the lanman password column. */ ptr = ENTRY_VAL(obj, NPF_LMPWD); if (!pdb_set_lanman_passwd(pw_buf, NULL)) return False; if (!strncasecmp(ptr, "NO PASSWORD", 11)) { pdb_set_acct_ctrl(pw_buf, pdb_get_acct_ctrl(pw_buf) | ACB_PWNOTREQ); } else { if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbpwd)) { DEBUG(0, ("malformed LM pwd entry: %s.\n", pdb_get_username(pw_buf))); return False; } if (!pdb_set_lanman_passwd(pw_buf, smbpwd)) return False; } /* Check the NT password column. */ ptr = ENTRY_VAL(obj, NPF_NTPWD); if (!pdb_set_nt_passwd(pw_buf, NULL)) return False; if (!(pdb_get_acct_ctrl(pw_buf) & ACB_PWNOTREQ) && strncasecmp(ptr, "NO PASSWORD", 11)) { if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbntpwd)) { DEBUG(0, ("malformed NT pwd entry:\ uid = %d.\n", pdb_get_uid(pw_buf))); return False; } if (!pdb_set_nt_passwd(pw_buf, smbntpwd)) return False; }