| 153 | | return NT_STATUS_UNSUCCESSFUL; |
| 154 | | } |
| 155 | | |
| 156 | | /* Lookup user information from a rid or username. */ |
| 157 | | static NTSTATUS query_user(struct winbindd_domain *domain, |
| 158 | | TALLOC_CTX *mem_ctx, |
| 159 | | const DOM_SID *user_sid, |
| 160 | | WINBIND_USERINFO *user_info) |
| 161 | | { |
| 162 | | return NT_STATUS_NO_SUCH_USER; |
| | 149 | size_t i; |
| | 150 | bool have_mapped; |
| | 151 | bool have_unmapped; |
| | 152 | |
| | 153 | *domain_name = NULL; |
| | 154 | *names = NULL; |
| | 155 | *types = NULL; |
| | 156 | |
| | 157 | if (!num_rids) { |
| | 158 | return NT_STATUS_OK; |
| | 159 | } |
| | 160 | |
| | 161 | *names = TALLOC_ARRAY(mem_ctx, char *, num_rids); |
| | 162 | *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids); |
| | 163 | |
| | 164 | if ((*names == NULL) || (*types == NULL)) { |
| | 165 | return NT_STATUS_NO_MEMORY; |
| | 166 | } |
| | 167 | |
| | 168 | have_mapped = have_unmapped = false; |
| | 169 | |
| | 170 | for (i=0; i<num_rids; i++) { |
| | 171 | DOM_SID sid; |
| | 172 | const char *dom = NULL, *nam = NULL; |
| | 173 | enum lsa_SidType type = SID_NAME_UNKNOWN; |
| | 174 | |
| | 175 | if (!sid_compose(&sid, domain_sid, rids[i])) { |
| | 176 | return NT_STATUS_INTERNAL_ERROR; |
| | 177 | } |
| | 178 | |
| | 179 | if (!lookup_sid(mem_ctx, &sid, &dom, &nam, &type)) { |
| | 180 | have_unmapped = true; |
| | 181 | (*types)[i] = SID_NAME_UNKNOWN; |
| | 182 | (*names)[i] = talloc_strdup(mem_ctx, ""); |
| | 183 | } else { |
| | 184 | have_mapped = true; |
| | 185 | (*types)[i] = type; |
| | 186 | (*names)[i] = CONST_DISCARD(char *, nam); |
| | 187 | } |
| | 188 | |
| | 189 | if (domain_name == NULL) { |
| | 190 | *domain_name = CONST_DISCARD(char *, dom); |
| | 191 | } else { |
| | 192 | char *dname = CONST_DISCARD(char *, dom); |
| | 193 | TALLOC_FREE(dname); |
| | 194 | } |
| | 195 | } |
| | 196 | |
| | 197 | if (!have_mapped) { |
| | 198 | return NT_STATUS_NONE_MAPPED; |
| | 199 | } |
| | 200 | if (!have_unmapped) { |
| | 201 | return NT_STATUS_OK; |
| | 202 | } |
| | 203 | return STATUS_SOME_UNMAPPED; |
| 210 | | /* Lookup group membership given a rid. */ |
| 211 | | static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, |
| | 251 | /* find the sequence number for a domain */ |
| | 252 | static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) |
| | 253 | { |
| | 254 | BOOL result; |
| | 255 | time_t seq_num; |
| | 256 | |
| | 257 | result = pdb_get_seq_num(&seq_num); |
| | 258 | if (!result) { |
| | 259 | *seq = 1; |
| | 260 | } |
| | 261 | |
| | 262 | *seq = (int) seq_num; |
| | 263 | /* *seq = 1; */ |
| | 264 | return NT_STATUS_OK; |
| | 265 | } |
| | 266 | |
| | 267 | static NTSTATUS lockout_policy(struct winbindd_domain *domain, |
| | 268 | TALLOC_CTX *mem_ctx, |
| | 269 | SAM_UNK_INFO_12 *policy) |
| | 270 | { |
| | 271 | /* actually we have that */ |
| | 272 | return NT_STATUS_NOT_IMPLEMENTED; |
| | 273 | } |
| | 274 | |
| | 275 | static NTSTATUS password_policy(struct winbindd_domain *domain, |
| | 276 | TALLOC_CTX *mem_ctx, |
| | 277 | SAM_UNK_INFO_1 *policy) |
| | 278 | { |
| | 279 | uint32 min_pass_len,pass_hist,password_properties; |
| | 280 | time_t u_expire, u_min_age; |
| | 281 | NTTIME nt_expire, nt_min_age; |
| | 282 | uint32 account_policy_temp; |
| | 283 | |
| | 284 | if ((policy = TALLOC_ZERO_P(mem_ctx, SAM_UNK_INFO_1)) == NULL) { |
| | 285 | return NT_STATUS_NO_MEMORY; |
| | 286 | } |
| | 287 | |
| | 288 | if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) { |
| | 289 | return NT_STATUS_ACCESS_DENIED; |
| | 290 | } |
| | 291 | min_pass_len = account_policy_temp; |
| | 292 | |
| | 293 | if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) { |
| | 294 | return NT_STATUS_ACCESS_DENIED; |
| | 295 | } |
| | 296 | pass_hist = account_policy_temp; |
| | 297 | |
| | 298 | if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) { |
| | 299 | return NT_STATUS_ACCESS_DENIED; |
| | 300 | } |
| | 301 | password_properties = account_policy_temp; |
| | 302 | |
| | 303 | if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) { |
| | 304 | return NT_STATUS_ACCESS_DENIED; |
| | 305 | } |
| | 306 | u_expire = account_policy_temp; |
| | 307 | |
| | 308 | if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) { |
| | 309 | return NT_STATUS_ACCESS_DENIED; |
| | 310 | } |
| | 311 | u_min_age = account_policy_temp; |
| | 312 | |
| | 313 | unix_to_nt_time_abs(&nt_expire, u_expire); |
| | 314 | unix_to_nt_time_abs(&nt_min_age, u_min_age); |
| | 315 | |
| | 316 | init_unk_info1(policy, (uint16)min_pass_len, (uint16)pass_hist, |
| | 317 | password_properties, nt_expire, nt_min_age); |
| | 318 | |
| | 319 | return NT_STATUS_OK; |
| | 320 | } |
| | 321 | |
| | 322 | /********************************************************************* |
| | 323 | BUILTIN specific functions. |
| | 324 | *********************************************************************/ |
| | 325 | |
| | 326 | /* list all domain groups */ |
| | 327 | static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain, |
| | 328 | TALLOC_CTX *mem_ctx, |
| | 329 | uint32 *num_entries, |
| | 330 | struct acct_info **info) |
| | 331 | { |
| | 332 | /* BUILTIN doesn't have domain groups */ |
| | 333 | *num_entries = 0; |
| | 334 | *info = NULL; |
| | 335 | return NT_STATUS_OK; |
| | 336 | } |
| | 337 | |
| | 338 | /* Query display info for a domain. This returns enough information plus a |
| | 339 | bit extra to give an overview of domain users for the User Manager |
| | 340 | application. */ |
| | 341 | static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain, |
| | 342 | TALLOC_CTX *mem_ctx, |
| | 343 | uint32 *num_entries, |
| | 344 | WINBIND_USERINFO **info) |
| | 345 | { |
| | 346 | /* We don't have users */ |
| | 347 | *num_entries = 0; |
| | 348 | *info = NULL; |
| | 349 | return NT_STATUS_OK; |
| | 350 | } |
| | 351 | |
| | 352 | /* Lookup user information from a rid or username. */ |
| | 353 | static NTSTATUS builtin_query_user(struct winbindd_domain *domain, |
| | 354 | TALLOC_CTX *mem_ctx, |
| | 355 | const DOM_SID *user_sid, |
| | 356 | WINBIND_USERINFO *user_info) |
| | 357 | { |
| | 358 | return NT_STATUS_NO_SUCH_USER; |
| | 359 | } |
| | 360 | |
| | 361 | static NTSTATUS builtin_lookup_groupmem(struct winbindd_domain *domain, |
| | 365 | uint32 **name_types) |
| | 366 | { |
| | 367 | *num_names = 0; |
| | 368 | *sid_mem = NULL; |
| | 369 | *names = NULL; |
| | 370 | *name_types = 0; |
| | 371 | return NT_STATUS_NO_SUCH_GROUP; |
| | 372 | } |
| | 373 | |
| | 374 | /* get a list of trusted domains - builtin domain */ |
| | 375 | static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain, |
| | 376 | TALLOC_CTX *mem_ctx, |
| | 377 | uint32 *num_domains, |
| | 378 | char ***names, |
| | 379 | char ***alt_names, |
| | 380 | DOM_SID **dom_sids) |
| | 381 | { |
| | 382 | *num_domains = 0; |
| | 383 | *names = NULL; |
| | 384 | *alt_names = NULL; |
| | 385 | *dom_sids = NULL; |
| | 386 | return NT_STATUS_OK; |
| | 387 | } |
| | 388 | |
| | 389 | /********************************************************************* |
| | 390 | SAM specific functions. |
| | 391 | *********************************************************************/ |
| | 392 | |
| | 393 | /* list all domain groups */ |
| | 394 | static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain, |
| | 395 | TALLOC_CTX *mem_ctx, |
| | 396 | uint32 *num_entries, |
| | 397 | struct acct_info **info) |
| | 398 | { |
| | 399 | return enum_groups_internal(domain, |
| | 400 | mem_ctx, |
| | 401 | num_entries, |
| | 402 | info, |
| | 403 | SID_NAME_DOM_GRP); |
| | 404 | } |
| | 405 | |
| | 406 | static NTSTATUS sam_query_user_list(struct winbindd_domain *domain, |
| | 407 | TALLOC_CTX *mem_ctx, |
| | 408 | uint32 *num_entries, |
| | 409 | WINBIND_USERINFO **info) |
| | 410 | { |
| | 411 | struct pdb_search *ps = pdb_search_users(ACB_NORMAL); |
| | 412 | struct samr_displayentry *entries = NULL; |
| | 413 | uint32 i; |
| | 414 | |
| | 415 | *num_entries = 0; |
| | 416 | *info = NULL; |
| | 417 | |
| | 418 | if (!ps) { |
| | 419 | return NT_STATUS_NO_MEMORY; |
| | 420 | } |
| | 421 | |
| | 422 | *num_entries = pdb_search_entries(ps, |
| | 423 | 1, 0xffffffff, |
| | 424 | &entries); |
| | 425 | |
| | 426 | *info = TALLOC_ZERO_ARRAY(mem_ctx, WINBIND_USERINFO, *num_entries); |
| | 427 | if (!(*info)) { |
| | 428 | pdb_search_destroy(ps); |
| | 429 | return NT_STATUS_NO_MEMORY; |
| | 430 | } |
| | 431 | |
| | 432 | for (i = 0; i < *num_entries; i++) { |
| | 433 | struct samr_displayentry *e = &entries[i]; |
| | 434 | |
| | 435 | (*info)[i].acct_name = talloc_strdup(mem_ctx, e->account_name ); |
| | 436 | (*info)[i].full_name = talloc_strdup(mem_ctx, e->fullname ); |
| | 437 | (*info)[i].homedir = NULL; |
| | 438 | (*info)[i].shell = NULL; |
| | 439 | sid_compose(&(*info)[i].user_sid, &domain->sid, e->rid); |
| | 440 | |
| | 441 | /* For the moment we set the primary group for |
| | 442 | every user to be the Domain Users group. |
| | 443 | There are serious problems with determining |
| | 444 | the actual primary group for large domains. |
| | 445 | This should really be made into a 'winbind |
| | 446 | force group' smb.conf parameter or |
| | 447 | something like that. */ |
| | 448 | |
| | 449 | sid_compose(&(*info)[i].group_sid, &domain->sid, |
| | 450 | DOMAIN_GROUP_RID_USERS); |
| | 451 | } |
| | 452 | |
| | 453 | pdb_search_destroy(ps); |
| | 454 | return NT_STATUS_OK; |
| | 455 | } |
| | 456 | |
| | 457 | /* Lookup user information from a rid or username. */ |
| | 458 | static NTSTATUS sam_query_user(struct winbindd_domain *domain, |
| | 459 | TALLOC_CTX *mem_ctx, |
| | 460 | const DOM_SID *user_sid, |
| | 461 | WINBIND_USERINFO *user_info) |
| | 462 | { |
| | 463 | struct samu *sampass = NULL; |
| | 464 | fstring sidstr; |
| | 465 | |
| | 466 | ZERO_STRUCTP(user_info); |
| | 467 | |
| | 468 | if (!sid_check_is_in_our_domain(user_sid)) { |
| | 469 | return NT_STATUS_NO_SUCH_USER; |
| | 470 | } |
| | 471 | |
| | 472 | sid_to_string(sidstr, user_sid); |
| | 473 | DEBUG(10,("sam_query_user: getting samu info for sid %s\n", |
| | 474 | sidstr )); |
| | 475 | |
| | 476 | if (!(sampass = samu_new(mem_ctx))) { |
| | 477 | return NT_STATUS_NO_MEMORY; |
| | 478 | } |
| | 479 | |
| | 480 | if (!pdb_getsampwsid(sampass, user_sid)) { |
| | 481 | TALLOC_FREE(sampass); |
| | 482 | return NT_STATUS_NO_SUCH_USER; |
| | 483 | } |
| | 484 | |
| | 485 | if (pdb_get_group_sid(sampass) == NULL) { |
| | 486 | TALLOC_FREE(sampass); |
| | 487 | return NT_STATUS_NO_SUCH_GROUP; |
| | 488 | } |
| | 489 | |
| | 490 | sid_to_string(sidstr, sampass->group_sid); |
| | 491 | DEBUG(10,("sam_query_user: group sid %s\n", sidstr )); |
| | 492 | |
| | 493 | sid_copy(&user_info->user_sid, user_sid); |
| | 494 | sid_copy(&user_info->group_sid, sampass->group_sid); |
| | 495 | |
| | 496 | user_info->acct_name = talloc_strdup(mem_ctx, sampass->username ? |
| | 497 | sampass->username : ""); |
| | 498 | user_info->full_name = talloc_strdup(mem_ctx, sampass->full_name ? |
| | 499 | sampass->full_name : ""); |
| | 500 | user_info->homedir = talloc_strdup(mem_ctx, sampass->home_dir ? |
| | 501 | sampass->home_dir : ""); |
| | 502 | if (sampass->unix_pw && sampass->unix_pw->pw_shell) { |
| | 503 | user_info->shell = talloc_strdup(mem_ctx, sampass->unix_pw->pw_shell); |
| | 504 | } else { |
| | 505 | user_info->shell = talloc_strdup(mem_ctx, ""); |
| | 506 | } |
| | 507 | user_info->primary_gid = sampass->unix_pw ? sampass->unix_pw->pw_gid : (gid_t)-1; |
| | 508 | |
| | 509 | TALLOC_FREE(sampass); |
| | 510 | return NT_STATUS_OK; |
| | 511 | } |
| | 512 | |
| | 513 | /* Lookup group membership given a rid. */ |
| | 514 | static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain, |
| | 515 | TALLOC_CTX *mem_ctx, |
| | 516 | const DOM_SID *group_sid, uint32 *num_names, |
| | 517 | DOM_SID **sid_mem, char ***names, |
| 306 | | /* find the sequence number for a domain */ |
| 307 | | static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) |
| 308 | | { |
| 309 | | BOOL result; |
| 310 | | time_t seq_num; |
| 311 | | |
| 312 | | result = pdb_get_seq_num(&seq_num); |
| 313 | | if (!result) { |
| 314 | | *seq = 1; |
| 315 | | } |
| 316 | | |
| 317 | | *seq = (int) seq_num; |
| 318 | | /* *seq = 1; */ |
| 319 | | return NT_STATUS_OK; |
| 320 | | } |
| 321 | | |
| 322 | | static NTSTATUS lockout_policy(struct winbindd_domain *domain, |
| 323 | | TALLOC_CTX *mem_ctx, |
| 324 | | SAM_UNK_INFO_12 *policy) |
| 325 | | { |
| 326 | | /* actually we have that */ |
| 327 | | return NT_STATUS_NOT_IMPLEMENTED; |
| 328 | | } |
| 329 | | |
| 330 | | static NTSTATUS password_policy(struct winbindd_domain *domain, |
| 331 | | TALLOC_CTX *mem_ctx, |
| 332 | | SAM_UNK_INFO_1 *policy) |
| 333 | | { |
| 334 | | uint32 min_pass_len,pass_hist,password_properties; |
| 335 | | time_t u_expire, u_min_age; |
| 336 | | NTTIME nt_expire, nt_min_age; |
| 337 | | uint32 account_policy_temp; |
| 338 | | |
| 339 | | if ((policy = TALLOC_ZERO_P(mem_ctx, SAM_UNK_INFO_1)) == NULL) { |
| 340 | | return NT_STATUS_NO_MEMORY; |
| 341 | | } |
| 342 | | |
| 343 | | if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) { |
| 344 | | return NT_STATUS_ACCESS_DENIED; |
| 345 | | } |
| 346 | | min_pass_len = account_policy_temp; |
| 347 | | |
| 348 | | if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) { |
| 349 | | return NT_STATUS_ACCESS_DENIED; |
| 350 | | } |
| 351 | | pass_hist = account_policy_temp; |
| 352 | | |
| 353 | | if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) { |
| 354 | | return NT_STATUS_ACCESS_DENIED; |
| 355 | | } |
| 356 | | password_properties = account_policy_temp; |
| 357 | | |
| 358 | | if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) { |
| 359 | | return NT_STATUS_ACCESS_DENIED; |
| 360 | | } |
| 361 | | u_expire = account_policy_temp; |
| 362 | | |
| 363 | | if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) { |
| 364 | | return NT_STATUS_ACCESS_DENIED; |
| 365 | | } |
| 366 | | u_min_age = account_policy_temp; |
| 367 | | |
| 368 | | unix_to_nt_time_abs(&nt_expire, u_expire); |
| 369 | | unix_to_nt_time_abs(&nt_min_age, u_min_age); |
| 370 | | |
| 371 | | init_unk_info1(policy, (uint16)min_pass_len, (uint16)pass_hist, |
| 372 | | password_properties, nt_expire, nt_min_age); |
| 373 | | |
| 374 | | return NT_STATUS_OK; |
| 375 | | } |
| 376 | | |
| 377 | | /* get a list of trusted domains */ |
| 378 | | static NTSTATUS trusted_domains(struct winbindd_domain *domain, |
| | 609 | /* get a list of trusted domains - sam */ |
| | 610 | static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain, |