00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023 #ifdef HAVE_LDAP
00024
00025 #define DEFAULT_DOMAIN_POLICY "Default Domain Policy"
00026 #define DEFAULT_DOMAIN_CONTROLLERS_POLICY "Default Domain Controllers Policy"
00027
00028
00029 struct gpo_table {
00030 const char *name;
00031 const char *guid_string;
00032 };
00033
00034 struct snapin_table {
00035 const char *name;
00036 const char *guid_string;
00037 ADS_STATUS (*snapin_fn)(ADS_STRUCT *, TALLOC_CTX *mem_ctx, const char *, const char *);
00038 };
00039
00040 #if 0
00041 static struct gpo_table gpo_default_policy[] = {
00042 { DEFAULT_DOMAIN_POLICY,
00043 "31B2F340-016D-11D2-945F-00C04FB984F9" },
00044 { DEFAULT_DOMAIN_CONTROLLERS_POLICY,
00045 "6AC1786C-016F-11D2-945F-00C04fB984F9" },
00046 { NULL, NULL }
00047 };
00048 #endif
00049
00050
00051
00052 static struct gpo_table gpo_cse_extensions[] = {
00053 { "Administrative Templates Extension",
00054 "35378EAC-683F-11D2-A89A-00C04FBBCFA2" },
00055 { "Microsoft Disc Quota",
00056 "3610EDA5-77EF-11D2-8DC5-00C04FA31A66" },
00057 { "EFS recovery",
00058 "B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A" },
00059 { "Folder Redirection",
00060 "25537BA6-77A8-11D2-9B6C-0000F8080861" },
00061 { "IP Security",
00062 "E437BC1C-AA7D-11D2-A382-00C04F991E27" },
00063 { "Internet Explorer Branding",
00064 "A2E30F80-D7DE-11d2-BBDE-00C04F86AE3B" },
00065 { "QoS Packet Scheduler",
00066 "426031c0-0b47-4852-b0ca-ac3d37bfcb39" },
00067 { "Scripts",
00068 "42B5FAAE-6536-11D2-AE5A-0000F87571E3" },
00069 { "Security",
00070 "827D319E-6EAC-11D2-A4EA-00C04F79F83A" },
00071 { "Software Installation",
00072 "C6DC5466-785A-11D2-84D0-00C04FB169F7" },
00073 { "Wireless Group Policy",
00074 "0ACDD40C-75AC-BAA0-BF6DE7E7FE63" },
00075 { NULL, NULL }
00076 };
00077
00078
00079 static struct snapin_table gpo_cse_snapin_extensions[] = {
00080 { "Administrative Templates",
00081 "0F6B957D-509E-11D1-A7CC-0000F87571E3", gpo_snapin_handler_none },
00082 { "Certificates",
00083 "53D6AB1D-2488-11D1-A28C-00C04FB94F17", gpo_snapin_handler_none },
00084 { "EFS recovery policy processing",
00085 "B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A", gpo_snapin_handler_none },
00086 { "Folder Redirection policy processing",
00087 "25537BA6-77A8-11D2-9B6C-0000F8080861", gpo_snapin_handler_none },
00088 { "Folder Redirection",
00089 "88E729D6-BDC1-11D1-BD2A-00C04FB9603F", gpo_snapin_handler_none },
00090 { "Registry policy processing",
00091 "35378EAC-683F-11D2-A89A-00C04FBBCFA2", gpo_snapin_handler_none },
00092 { "Remote Installation Services",
00093 "3060E8CE-7020-11D2-842D-00C04FA372D4", gpo_snapin_handler_none },
00094 { "Security Settings",
00095 "803E14A0-B4FB-11D0-A0D0-00A0C90F574B", gpo_snapin_handler_security_settings },
00096 { "Security policy processing",
00097 "827D319E-6EAC-11D2-A4EA-00C04F79F83A", gpo_snapin_handler_security_settings },
00098 { "unknown",
00099 "3060E8D0-7020-11D2-842D-00C04FA372D4", gpo_snapin_handler_none },
00100 { "unknown2",
00101 "53D6AB1B-2488-11D1-A28C-00C04FB94F17", gpo_snapin_handler_none },
00102 { NULL, NULL, NULL }
00103 };
00104
00105 static const char *name_to_guid_string(const char *name, struct gpo_table *table)
00106 {
00107 int i;
00108
00109 for (i = 0; table[i].name; i++) {
00110 if (strequal(name, table[i].name)) {
00111 return table[i].guid_string;
00112 }
00113 }
00114
00115 return NULL;
00116 }
00117
00118 static const char *guid_string_to_name(const char *guid_string, struct gpo_table *table)
00119 {
00120 int i;
00121
00122 for (i = 0; table[i].guid_string; i++) {
00123 if (strequal(guid_string, table[i].guid_string)) {
00124 return table[i].name;
00125 }
00126 }
00127
00128 return NULL;
00129 }
00130
00131 static const char *snapin_guid_string_to_name(const char *guid_string,
00132 struct snapin_table *table)
00133 {
00134 int i;
00135 for (i = 0; table[i].guid_string; i++) {
00136 if (strequal(guid_string, table[i].guid_string)) {
00137 return table[i].name;
00138 }
00139 }
00140 return NULL;
00141 }
00142
00143 #if 0
00144 static const char *default_gpo_name_to_guid_string(const char *name)
00145 {
00146 return name_to_guid_string(name, gpo_default_policy);
00147 }
00148
00149 static const char *default_gpo_guid_string_to_name(const char *guid)
00150 {
00151 return guid_string_to_name(guid, gpo_default_policy);
00152 }
00153 #endif
00154
00155 const char *cse_gpo_guid_string_to_name(const char *guid)
00156 {
00157 return guid_string_to_name(guid, gpo_cse_extensions);
00158 }
00159
00160 static const char *cse_gpo_name_to_guid_string(const char *name)
00161 {
00162 return name_to_guid_string(name, gpo_cse_extensions);
00163 }
00164
00165 const char *cse_snapin_gpo_guid_string_to_name(const char *guid)
00166 {
00167 return snapin_guid_string_to_name(guid, gpo_cse_snapin_extensions);
00168 }
00169
00170 void dump_gp_ext(struct GP_EXT *gp_ext, int debuglevel)
00171 {
00172 int lvl = debuglevel;
00173 int i;
00174
00175 if (gp_ext == NULL) {
00176 return;
00177 }
00178
00179 DEBUG(lvl,("\t---------------------\n\n"));
00180 DEBUGADD(lvl,("\tname:\t\t\t%s\n", gp_ext->gp_extension));
00181
00182 for (i=0; i< gp_ext->num_exts; i++) {
00183
00184 DEBUGADD(lvl,("\textension:\t\t\t%s\n", gp_ext->extensions_guid[i]));
00185 DEBUGADD(lvl,("\textension (name):\t\t\t%s\n", gp_ext->extensions[i]));
00186
00187 DEBUGADD(lvl,("\tsnapin:\t\t\t%s\n", gp_ext->snapins_guid[i]));
00188 DEBUGADD(lvl,("\tsnapin (name):\t\t\t%s\n", gp_ext->snapins[i]));
00189 }
00190 }
00191
00192 void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo, int debuglevel)
00193 {
00194 int lvl = debuglevel;
00195
00196 if (gpo == NULL) {
00197 return;
00198 }
00199
00200 DEBUG(lvl,("---------------------\n\n"));
00201
00202 DEBUGADD(lvl,("name:\t\t\t%s\n", gpo->name));
00203 DEBUGADD(lvl,("displayname:\t\t%s\n", gpo->display_name));
00204 DEBUGADD(lvl,("version:\t\t%d (0x%08x)\n", gpo->version, gpo->version));
00205 DEBUGADD(lvl,("version_user:\t\t%d (0x%04x)\n", GPO_VERSION_USER(gpo->version),
00206 GPO_VERSION_USER(gpo->version)));
00207 DEBUGADD(lvl,("version_machine:\t%d (0x%04x)\n", GPO_VERSION_MACHINE(gpo->version),
00208 GPO_VERSION_MACHINE(gpo->version)));
00209 DEBUGADD(lvl,("filesyspath:\t\t%s\n", gpo->file_sys_path));
00210 DEBUGADD(lvl,("dspath:\t\t%s\n", gpo->ds_path));
00211
00212 DEBUGADD(lvl,("options:\t\t%d ", gpo->options));
00213 if (gpo->options & GPFLAGS_USER_SETTINGS_DISABLED) {
00214 DEBUGADD(lvl,("GPFLAGS_USER_SETTINGS_DISABLED "));
00215 }
00216 if (gpo->options & GPFLAGS_MACHINE_SETTINGS_DISABLED) {
00217 DEBUGADD(lvl,("GPFLAGS_MACHINE_SETTINGS_DISABLED"));
00218 }
00219 DEBUGADD(lvl,("\n"));
00220
00221 DEBUGADD(lvl,("link:\t\t\t%s\n", gpo->link));
00222 DEBUGADD(lvl,("link_type:\t\t%d ", gpo->link_type));
00223 switch (gpo->link_type) {
00224 case GP_LINK_UNKOWN:
00225 DEBUGADD(lvl,("GP_LINK_UNKOWN\n"));
00226 break;
00227 case GP_LINK_OU:
00228 DEBUGADD(lvl,("GP_LINK_OU\n"));
00229 break;
00230 case GP_LINK_DOMAIN:
00231 DEBUGADD(lvl,("GP_LINK_DOMAIN\n"));
00232 break;
00233 case GP_LINK_SITE:
00234 DEBUGADD(lvl,("GP_LINK_SITE\n"));
00235 break;
00236 case GP_LINK_MACHINE:
00237 DEBUGADD(lvl,("GP_LINK_MACHINE\n"));
00238 break;
00239 default:
00240 break;
00241 }
00242
00243 if (gpo->machine_extensions) {
00244
00245 struct GP_EXT gp_ext;
00246 ADS_STATUS status;
00247
00248 DEBUGADD(lvl,("machine_extensions:\t%s\n", gpo->machine_extensions));
00249
00250 status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
00251 if (!ADS_ERR_OK(status)) {
00252 return;
00253 }
00254 dump_gp_ext(&gp_ext, lvl);
00255 }
00256
00257 if (gpo->user_extensions) {
00258
00259 struct GP_EXT gp_ext;
00260 ADS_STATUS status;
00261
00262 DEBUGADD(lvl,("user_extensions:\t%s\n", gpo->user_extensions));
00263
00264 status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
00265 if (!ADS_ERR_OK(status)) {
00266 return;
00267 }
00268 dump_gp_ext(&gp_ext, lvl);
00269 }
00270 }
00271
00272 void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link)
00273 {
00274 ADS_STATUS status;
00275 int i;
00276 int lvl = 10;
00277
00278 if (gp_link == NULL) {
00279 return;
00280 }
00281
00282 DEBUG(lvl,("---------------------\n\n"));
00283
00284 DEBUGADD(lvl,("gplink: %s\n", gp_link->gp_link));
00285 DEBUGADD(lvl,("gpopts: %d ", gp_link->gp_opts));
00286 switch (gp_link->gp_opts) {
00287 case GPOPTIONS_INHERIT:
00288 DEBUGADD(lvl,("GPOPTIONS_INHERIT\n"));
00289 break;
00290 case GPOPTIONS_BLOCK_INHERITANCE:
00291 DEBUGADD(lvl,("GPOPTIONS_BLOCK_INHERITANCE\n"));
00292 break;
00293 default:
00294 break;
00295 }
00296
00297 DEBUGADD(lvl,("num links: %d\n", gp_link->num_links));
00298
00299 for (i = 0; i < gp_link->num_links; i++) {
00300
00301 DEBUGADD(lvl,("---------------------\n\n"));
00302
00303 DEBUGADD(lvl,("link: #%d\n", i + 1));
00304 DEBUGADD(lvl,("name: %s\n", gp_link->link_names[i]));
00305
00306 DEBUGADD(lvl,("opt: %d ", gp_link->link_opts[i]));
00307 if (gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED) {
00308 DEBUGADD(lvl,("GPO_LINK_OPT_ENFORCED "));
00309 }
00310 if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
00311 DEBUGADD(lvl,("GPO_LINK_OPT_DISABLED"));
00312 }
00313 DEBUGADD(lvl,("\n"));
00314
00315 if (ads != NULL && mem_ctx != NULL) {
00316
00317 struct GROUP_POLICY_OBJECT gpo;
00318
00319 status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i], NULL, NULL, &gpo);
00320 if (!ADS_ERR_OK(status)) {
00321 DEBUG(lvl,("get gpo for %s failed: %s\n", gp_link->link_names[i], ads_errstr(status)));
00322 return;
00323 }
00324 dump_gpo(mem_ctx, &gpo, lvl);
00325 }
00326 }
00327 }
00328
00329 ADS_STATUS process_extension_with_snapin(ADS_STRUCT *ads,
00330 TALLOC_CTX *mem_ctx,
00331 const char *extension_guid,
00332 const char *snapin_guid)
00333 {
00334 int i;
00335
00336 for (i=0; gpo_cse_snapin_extensions[i].guid_string; i++) {
00337
00338 if (strcmp(gpo_cse_snapin_extensions[i].guid_string, snapin_guid) == 0) {
00339
00340 return gpo_cse_snapin_extensions[i].snapin_fn(ads, mem_ctx,
00341 extension_guid, snapin_guid);
00342 }
00343 }
00344
00345 DEBUG(10,("process_extension_with_snapin: no snapin handler for extension %s (%s) found\n",
00346 extension_guid, snapin_guid));
00347
00348 return ADS_ERROR(LDAP_SUCCESS);
00349 }
00350
00351 ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads,
00352 TALLOC_CTX *mem_ctx,
00353 struct GROUP_POLICY_OBJECT *gpo,
00354 const char *extension_guid,
00355 uint32 flags)
00356 {
00357 ADS_STATUS status;
00358 struct GP_EXT gp_ext;
00359 int i;
00360
00361 if (flags & GPO_LIST_FLAG_MACHINE) {
00362
00363 if (gpo->machine_extensions) {
00364
00365 status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
00366
00367 if (!ADS_ERR_OK(status)) {
00368 return status;
00369 }
00370
00371 } else {
00372
00373 return ADS_ERROR(LDAP_SUCCESS);
00374 }
00375
00376 } else {
00377
00378 if (gpo->user_extensions) {
00379
00380 status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
00381
00382 if (!ADS_ERR_OK(status)) {
00383 return status;
00384 }
00385 } else {
00386
00387 return ADS_ERROR(LDAP_SUCCESS);
00388 }
00389 }
00390
00391 for (i=0; i<gp_ext.num_exts; i++) {
00392
00393 if (extension_guid && !strequal(extension_guid, gp_ext.extensions_guid[i])) {
00394 continue;
00395 }
00396
00397 status = process_extension_with_snapin(ads, mem_ctx, gp_ext.extensions_guid[i],
00398 gp_ext.snapins_guid[i]);
00399 if (!ADS_ERR_OK(status)) {
00400 return status;
00401 }
00402 }
00403
00404 return ADS_ERROR(LDAP_SUCCESS);
00405 }
00406
00407 ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
00408 TALLOC_CTX *mem_ctx,
00409 struct GROUP_POLICY_OBJECT **gpo_list,
00410 const char *extensions_guid,
00411 uint32 flags)
00412 {
00413 ADS_STATUS status;
00414 struct GROUP_POLICY_OBJECT *gpo = *gpo_list;
00415
00416 for (gpo = *gpo_list; gpo; gpo = gpo->next) {
00417
00418 status = gpo_process_a_gpo(ads, mem_ctx, gpo,
00419 extensions_guid, flags);
00420
00421 if (!ADS_ERR_OK(status)) {
00422 return status;
00423 }
00424
00425 }
00426
00427 return ADS_ERROR(LDAP_SUCCESS);
00428 }
00429
00430 ADS_STATUS gpo_snapin_handler_none(ADS_STRUCT *ads,
00431 TALLOC_CTX *mem_ctx,
00432 const char *extension_guid,
00433 const char *snapin_guid)
00434 {
00435 DEBUG(10,("gpo_snapin_handler_none\n"));
00436
00437 return ADS_ERROR(LDAP_SUCCESS);
00438 }
00439
00440 ADS_STATUS gpo_snapin_handler_security_settings(ADS_STRUCT *ads,
00441 TALLOC_CTX *mem_ctx,
00442 const char *extension_guid,
00443 const char *snapin_guid)
00444 {
00445 DEBUG(10,("gpo_snapin_handler_security_settings\n"));
00446
00447 return ADS_ERROR(LDAP_SUCCESS);
00448 }
00449
00450 ADS_STATUS gpo_lockout_policy(ADS_STRUCT *ads,
00451 TALLOC_CTX *mem_ctx,
00452 const char *hostname,
00453 SAM_UNK_INFO_12 *lockout_policy)
00454 {
00455 return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
00456 }
00457
00458 ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
00459 TALLOC_CTX *mem_ctx,
00460 const char *hostname,
00461 SAM_UNK_INFO_1 *password_policy)
00462 {
00463 ADS_STATUS status;
00464 struct GROUP_POLICY_OBJECT *gpo_list;
00465 const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
00466 char *filter, *dn;
00467 LDAPMessage *res = NULL;
00468 uint32 uac;
00469
00470 filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", hostname);
00471 if (filter == NULL) {
00472 return ADS_ERROR(LDAP_NO_MEMORY);
00473 }
00474
00475 status = ads_do_search_all(ads, ads->config.bind_path,
00476 LDAP_SCOPE_SUBTREE,
00477 filter, attrs, &res);
00478
00479 if (!ADS_ERR_OK(status)) {
00480 return status;
00481 }
00482
00483 if (ads_count_replies(ads, res) != 1) {
00484 ads_msgfree(ads, res);
00485 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
00486 }
00487
00488 dn = ads_get_dn(ads, res);
00489 if (dn == NULL) {
00490 ads_msgfree(ads, res);
00491 return ADS_ERROR(LDAP_NO_MEMORY);
00492 }
00493
00494 if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
00495 ads_msgfree(ads, res);
00496 ads_memfree(ads, dn);
00497 return ADS_ERROR(LDAP_NO_MEMORY);
00498 }
00499
00500 ads_msgfree(ads, res);
00501
00502 if (!(uac & UF_WORKSTATION_TRUST_ACCOUNT)) {
00503 ads_memfree(ads, dn);
00504 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
00505 }
00506
00507 status = ads_get_gpo_list(ads, mem_ctx, dn, GPO_LIST_FLAG_MACHINE, &gpo_list);
00508 if (!ADS_ERR_OK(status)) {
00509 ads_memfree(ads, dn);
00510 return status;
00511 }
00512
00513 ads_memfree(ads, dn);
00514
00515 status = gpo_process_gpo_list(ads, mem_ctx, &gpo_list,
00516 cse_gpo_name_to_guid_string("Security"),
00517 GPO_LIST_FLAG_MACHINE);
00518 if (!ADS_ERR_OK(status)) {
00519 return status;
00520 }
00521
00522 return ADS_ERROR(LDAP_SUCCESS);
00523 }
00524
00525
00526
00527
00528
00529
00530 NTSTATUS check_refresh_gpo(ADS_STRUCT *ads,
00531 TALLOC_CTX *mem_ctx,
00532 struct GROUP_POLICY_OBJECT *gpo,
00533 struct cli_state **cli_out)
00534 {
00535 NTSTATUS result;
00536 char *server, *share, *nt_path, *unix_path;
00537 uint32 sysvol_gpt_version = 0;
00538 char *display_name;
00539 struct cli_state *cli = NULL;
00540
00541 result = ads_gpo_explode_filesyspath(ads, mem_ctx, gpo->file_sys_path,
00542 &server, &share, &nt_path, &unix_path);
00543
00544 if (!NT_STATUS_IS_OK(result)) {
00545 goto out;
00546 }
00547
00548 result = ads_gpo_get_sysvol_gpt_version(ads, mem_ctx,
00549 unix_path,
00550 &sysvol_gpt_version,
00551 &display_name);
00552 if (!NT_STATUS_IS_OK(result) &&
00553 !NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_FILE)) {
00554 DEBUG(10,("check_refresh_gpo: failed to get local gpt version: %s\n",
00555 nt_errstr(result)));
00556 goto out;
00557 }
00558
00559 while (gpo->version > sysvol_gpt_version) {
00560
00561 DEBUG(1,("check_refresh_gpo: need to refresh GPO\n"));
00562
00563 if (*cli_out == NULL) {
00564
00565 result = cli_full_connection(&cli, global_myname(),
00566 server,
00567 NULL, 0,
00568 share, "A:",
00569 ads->auth.user_name, NULL, ads->auth.password,
00570 CLI_FULL_CONNECTION_USE_KERBEROS,
00571 Undefined, NULL);
00572 if (!NT_STATUS_IS_OK(result)) {
00573 DEBUG(10,("check_refresh_gpo: failed to connect: %s\n", nt_errstr(result)));
00574 goto out;
00575 }
00576
00577 *cli_out = cli;
00578 }
00579
00580 result = ads_fetch_gpo_files(ads, mem_ctx, *cli_out, gpo);
00581 if (!NT_STATUS_IS_OK(result)) {
00582 goto out;
00583 }
00584
00585 result = ads_gpo_get_sysvol_gpt_version(ads, mem_ctx,
00586 unix_path,
00587 &sysvol_gpt_version,
00588 &display_name);
00589 if (!NT_STATUS_IS_OK(result)) {
00590 DEBUG(10,("check_refresh_gpo: failed to get local gpt version: %s\n",
00591 nt_errstr(result)));
00592 goto out;
00593 }
00594
00595 if (gpo->version == sysvol_gpt_version) {
00596 break;
00597 }
00598 }
00599
00600 DEBUG(10,("Name:\t\t\t%s\n", gpo->display_name));
00601 DEBUGADD(10,("sysvol GPT version:\t%d (user: %d, machine: %d)\n",
00602 sysvol_gpt_version,
00603 GPO_VERSION_USER(sysvol_gpt_version),
00604 GPO_VERSION_MACHINE(sysvol_gpt_version)));
00605 DEBUGADD(10,("LDAP GPO version:\t%d (user: %d, machine: %d)\n",
00606 gpo->version,
00607 GPO_VERSION_USER(gpo->version),
00608 GPO_VERSION_MACHINE(gpo->version)));
00609
00610 result = NT_STATUS_OK;
00611
00612 out:
00613 return result;
00614
00615 }
00616
00617
00618
00619
00620
00621
00622 NTSTATUS check_refresh_gpo_list(ADS_STRUCT *ads,
00623 TALLOC_CTX *mem_ctx,
00624 struct GROUP_POLICY_OBJECT *gpo_list)
00625 {
00626 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
00627 struct cli_state *cli = NULL;
00628 struct GROUP_POLICY_OBJECT *gpo;
00629
00630 for (gpo = gpo_list; gpo; gpo = gpo->next) {
00631
00632 result = check_refresh_gpo(ads, mem_ctx, gpo, &cli);
00633 if (!NT_STATUS_IS_OK(result)) {
00634 goto out;
00635 }
00636 }
00637
00638 result = NT_STATUS_OK;
00639
00640 out:
00641 if (cli) {
00642 cli_shutdown(cli);
00643 }
00644
00645 return result;
00646 }
00647
00648 #endif