X-Git-Url: http://git.samba.org/samba.git/?p=sfrench%2Fsamba-autobuild%2F.git;a=blobdiff_plain;f=source%2Futils%2Fnet.c;h=34f580f4d1c058c43f203ddade03b316fc157a2a;hp=fcc8b4abe1d8a6adc0eeacc8cab7f9ff9f40e3ee;hb=407e6e695b8366369b7c76af1ff76869b45347b3;hpb=7a78c3605e203bd8e0d7ae244605f076a5d0b0bc diff --git a/source/utils/net.c b/source/utils/net.c index fcc8b4abe1d..34f580f4d1c 100644 --- a/source/utils/net.c +++ b/source/utils/net.c @@ -13,7 +13,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -38,7 +38,7 @@ /*****************************************************/ #include "includes.h" -#include "../utils/net.h" +#include "utils/net.h" /***********************************************************************/ /* Beginning of internationalization section. Translatable constants */ @@ -65,22 +65,32 @@ const char *opt_workgroup = NULL; int opt_long_list_entries = 0; int opt_reboot = 0; int opt_force = 0; +int opt_stdin = 0; int opt_port = 0; +int opt_verbose = 0; int opt_maxusers = -1; const char *opt_comment = ""; -const char *opt_container = "cn=Users"; +const char *opt_container = NULL; int opt_flags = -1; int opt_timeout = 0; const char *opt_target_workgroup = NULL; int opt_machine_pass = 0; BOOL opt_localgroup = False; BOOL opt_domaingroup = False; +static BOOL do_talloc_report=False; const char *opt_newntname = ""; int opt_rid = 0; +int opt_acls = 0; +int opt_attrs = 0; +int opt_timestamps = 0; +const char *opt_exclude = NULL; +const char *opt_destination = NULL; +BOOL opt_testmode = False; BOOL opt_have_ip = False; struct in_addr opt_dest_ip; +extern struct in_addr loopback_ip; extern BOOL AllowDebugChange; uint32 get_sec_channel_type(const char *param) @@ -121,56 +131,90 @@ int net_run_function(int argc, const char **argv, struct functable *table, if (StrCaseCmp(argv[0], table[i].funcname) == 0) return table[i].fn(argc-1, argv+1); } - d_printf("No command: %s\n", argv[0]); + d_fprintf(stderr, "No command: %s\n", argv[0]); return usage_fn(argc, argv); } +/* + * run a function from a function table. + */ +int net_run_function2(int argc, const char **argv, const char *whoami, + struct functable2 *table) +{ + int i; + + if (argc != 0) { + for (i=0; table[i].funcname; i++) { + if (StrCaseCmp(argv[0], table[i].funcname) == 0) + return table[i].fn(argc-1, argv+1); + } + } + + for (i=0; table[i].funcname != NULL; i++) { + d_printf("%s %-15s %s\n", whoami, table[i].funcname, + table[i].helptext); + } + + return -1; +} /**************************************************************************** -connect to \\server\ipc$ +connect to \\server\service ****************************************************************************/ -NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip, - const char *server_name) + +NTSTATUS connect_to_service(struct cli_state **c, struct in_addr *server_ip, + const char *server_name, + const char *service_name, + const char *service_type) { NTSTATUS nt_status; if (!opt_password && !opt_machine_pass) { char *pass = getpass("Password:"); if (pass) { - opt_password = strdup(pass); + opt_password = SMB_STRDUP(pass); } } - - nt_status = cli_full_connection(c, opt_requester_name, server_name, + + nt_status = cli_full_connection(c, NULL, server_name, server_ip, opt_port, - "IPC$", "IPC", + service_name, service_type, opt_user_name, opt_workgroup, opt_password, 0, Undefined, NULL); - + if (NT_STATUS_IS_OK(nt_status)) { return nt_status; } else { - DEBUG(1,("Cannot connect to server. Error was %s\n", - nt_errstr(nt_status))); + d_fprintf(stderr, "Could not connect to server %s\n", server_name); /* Display a nicer message depending on the result */ if (NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_LOGON_FAILURE)) - d_printf("The username or password was not correct.\n"); + d_fprintf(stderr, "The username or password was not correct.\n"); if (NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_ACCOUNT_LOCKED_OUT)) - d_printf("The account was locked out.\n"); + d_fprintf(stderr, "The account was locked out.\n"); if (NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_ACCOUNT_DISABLED)) - d_printf("The account was disabled.\n"); + d_fprintf(stderr, "The account was disabled.\n"); return nt_status; } } + +/**************************************************************************** +connect to \\server\ipc$ +****************************************************************************/ +NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip, + const char *server_name) +{ + return connect_to_service(c, server_ip, server_name, "IPC$", "IPC"); +} + /**************************************************************************** connect to \\server\ipc$ anonymously ****************************************************************************/ @@ -194,14 +238,124 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c, } /**************************************************************************** - Use the local machine's password for this session + Return malloced user@realm for krb5 login. +****************************************************************************/ + +static char *get_user_and_realm(const char *username) +{ + char *user_and_realm = NULL; + + if (!username) { + return NULL; + } + if (strchr_m(username, '@')) { + user_and_realm = SMB_STRDUP(username); + } else { + if (asprintf(&user_and_realm, "%s@%s", username, lp_realm()) == -1) { + user_and_realm = NULL; + } + } + return user_and_realm; +} + +/**************************************************************************** +connect to \\server\ipc$ using KRB5 ****************************************************************************/ + +NTSTATUS connect_to_ipc_krb5(struct cli_state **c, + struct in_addr *server_ip, const char *server_name) +{ + NTSTATUS nt_status; + char *user_and_realm = NULL; + + if (!opt_password && !opt_machine_pass) { + char *pass = getpass("Password:"); + if (pass) { + opt_password = SMB_STRDUP(pass); + } + } + + user_and_realm = get_user_and_realm(opt_user_name); + if (!user_and_realm) { + return NT_STATUS_NO_MEMORY; + } + + nt_status = cli_full_connection(c, NULL, server_name, + server_ip, opt_port, + "IPC$", "IPC", + user_and_realm, opt_workgroup, + opt_password, CLI_FULL_CONNECTION_USE_KERBEROS, + Undefined, NULL); + + SAFE_FREE(user_and_realm); + + if (NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } else { + DEBUG(1,("Cannot connect to server using kerberos. Error was %s\n", nt_errstr(nt_status))); + return nt_status; + } +} + +/** + * Connect a server and open a given pipe + * + * @param cli_dst A cli_state + * @param pipe The pipe to open + * @param got_pipe boolean that stores if we got a pipe + * + * @return Normal NTSTATUS return. + **/ +NTSTATUS connect_dst_pipe(struct cli_state **cli_dst, struct rpc_pipe_client **pp_pipe_hnd, int pipe_num) +{ + NTSTATUS nt_status; + char *server_name = SMB_STRDUP("127.0.0.1"); + struct cli_state *cli_tmp = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; + + if (server_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (opt_destination) { + SAFE_FREE(server_name); + if ((server_name = SMB_STRDUP(opt_destination)) == NULL) { + return NT_STATUS_NO_MEMORY; + } + } + + /* make a connection to a named pipe */ + nt_status = connect_to_ipc(&cli_tmp, NULL, server_name); + if (!NT_STATUS_IS_OK(nt_status)) { + SAFE_FREE(server_name); + return nt_status; + } + + pipe_hnd = cli_rpc_pipe_open_noauth(cli_tmp, pipe_num, &nt_status); + if (!pipe_hnd) { + DEBUG(0, ("couldn't not initialize pipe\n")); + cli_shutdown(cli_tmp); + SAFE_FREE(server_name); + return nt_status; + } + + *cli_dst = cli_tmp; + *pp_pipe_hnd = pipe_hnd; + SAFE_FREE(server_name); + + return nt_status; +} + +/**************************************************************************** + Use the local machine's password for this session. +****************************************************************************/ + int net_use_machine_password(void) { char *user_name = NULL; if (!secrets_init()) { - d_printf("ERROR: Unable to open secrets database\n"); + d_fprintf(stderr, "ERROR: Unable to open secrets database\n"); exit(1); } @@ -214,17 +368,18 @@ int net_use_machine_password(void) return 0; } -BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_name) +BOOL net_find_server(const char *domain, unsigned flags, struct in_addr *server_ip, char **server_name) { + const char *d = domain ? domain : opt_target_workgroup; if (opt_host) { - *server_name = strdup(opt_host); + *server_name = SMB_STRDUP(opt_host); } if (opt_have_ip) { *server_ip = opt_dest_ip; if (!*server_name) { - *server_name = strdup(inet_ntoa(opt_dest_ip)); + *server_name = SMB_STRDUP(inet_ntoa(opt_dest_ip)); } } else if (*server_name) { /* resolve the IP address */ @@ -235,43 +390,41 @@ BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_na } else if (flags & NET_FLAGS_PDC) { struct in_addr pdc_ip; - if (get_pdc_ip(opt_target_workgroup, &pdc_ip)) { + if (get_pdc_ip(d, &pdc_ip)) { fstring dc_name; if (is_zero_ip(pdc_ip)) return False; - if ( !name_status_find(opt_target_workgroup, 0x1b, 0x20, pdc_ip, dc_name) ) + if ( !name_status_find(d, 0x1b, 0x20, pdc_ip, dc_name) ) return False; - *server_name = strdup(dc_name); + *server_name = SMB_STRDUP(dc_name); *server_ip = pdc_ip; } - } else if (flags & NET_FLAGS_DMB) { struct in_addr msbrow_ip; /* if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */ - if (!resolve_name(opt_target_workgroup, &msbrow_ip, 0x1B)) { + if (!resolve_name(d, &msbrow_ip, 0x1B)) { DEBUG(1,("Unable to resolve domain browser via name lookup\n")); return False; } else { *server_ip = msbrow_ip; } - *server_name = strdup(inet_ntoa(opt_dest_ip)); + *server_name = SMB_STRDUP(inet_ntoa(opt_dest_ip)); } else if (flags & NET_FLAGS_MASTER) { struct in_addr brow_ips; - if (!resolve_name(opt_target_workgroup, &brow_ips, 0x1D)) { + if (!resolve_name(d, &brow_ips, 0x1D)) { /* go looking for workgroups */ DEBUG(1,("Unable to resolve master browser via name lookup\n")); return False; } else { *server_ip = brow_ips; } - *server_name = strdup(inet_ntoa(opt_dest_ip)); + *server_name = SMB_STRDUP(inet_ntoa(opt_dest_ip)); } else if (!(flags & NET_FLAGS_LOCALHOST_DEFAULT_INSANE)) { - extern struct in_addr loopback_ip; *server_ip = loopback_ip; - *server_name = strdup("127.0.0.1"); + *server_name = SMB_STRDUP("127.0.0.1"); } if (!server_name || !*server_name) { @@ -298,17 +451,27 @@ BOOL net_find_pdc(struct in_addr *server_ip, fstring server_name, const char *do return False; } +struct cli_state *net_make_ipc_connection( unsigned flags ) +{ + return net_make_ipc_connection_ex( NULL, NULL, NULL, flags ); +} -struct cli_state *net_make_ipc_connection(unsigned flags) +struct cli_state *net_make_ipc_connection_ex( const char *domain, const char *server, + struct in_addr *ip, unsigned flags) { char *server_name = NULL; struct in_addr server_ip; struct cli_state *cli = NULL; NTSTATUS nt_status; - if (!net_find_server(flags, &server_ip, &server_name)) { - d_printf("\nUnable to find a suitable server\n"); - return NULL; + if ( !server || !ip ) { + if (!net_find_server(domain, flags, &server_ip, &server_name)) { + d_fprintf(stderr, "Unable to find a suitable server\n"); + return NULL; + } + } else { + server_name = SMB_STRDUP( server ); + server_ip = *ip; } if (flags & NET_FLAGS_ANONYMOUS) { @@ -317,10 +480,17 @@ struct cli_state *net_make_ipc_connection(unsigned flags) nt_status = connect_to_ipc(&cli, &server_ip, server_name); } + /* store the server in the affinity cache if it was a PDC */ + + if ( (flags & NET_FLAGS_PDC) && NT_STATUS_IS_OK(nt_status) ) + saf_store( cli->server_domain, cli->desthost ); + SAFE_FREE(server_name); if (NT_STATUS_IS_OK(nt_status)) { return cli; } else { + d_fprintf(stderr, "Connection failed: %s\n", + nt_errstr(nt_status)); return NULL; } } @@ -350,33 +520,44 @@ static int net_group(int argc, const char **argv) static int net_join(int argc, const char **argv) { - if (net_ads_check() == 0) { + if (net_ads_check_our_domain() == 0) { if (net_ads_join(argc, argv) == 0) return 0; else - d_printf("ADS join did not work, falling back to RPC...\n"); + d_fprintf(stderr, "ADS join did not work, falling back to RPC...\n"); } return net_rpc_join(argc, argv); } static int net_changetrustpw(int argc, const char **argv) { - if (net_ads_check() == 0) + if (net_ads_check_our_domain() == 0) return net_ads_changetrustpw(argc, argv); return net_rpc_changetrustpw(argc, argv); } +static void set_line_buffering(FILE *f) +{ + setvbuf(f, NULL, _IOLBF, 0); +} + static int net_changesecretpw(int argc, const char **argv) { char *trust_pw; uint32 sec_channel_type = SEC_CHAN_WKSTA; if(opt_force) { - trust_pw = getpass("Enter machine password: "); + if (opt_stdin) { + set_line_buffering(stdin); + set_line_buffering(stdout); + set_line_buffering(stderr); + } + + trust_pw = get_pass("Enter machine password: ", opt_stdin); if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) { - d_printf("Unable to write the machine account password in the secrets database"); + d_fprintf(stderr, "Unable to write the machine account password in the secrets database"); return 1; } else { @@ -422,16 +603,24 @@ static int net_getlocalsid(int argc, const char **argv) name = global_myname(); } - if(!initialize_password_db(False)) { + if(!initialize_password_db(False, NULL)) { DEBUG(0, ("WARNING: Could not open passdb - local sid may not reflect passdb\n" "backend knowlege (such as the sid stored in LDAP)\n")); } + /* first check to see if we can even access secrets, so we don't + panic when we can't. */ + + if (!secrets_init()) { + d_fprintf(stderr, "Unable to open secrets.tdb. Can't fetch domain SID for name: %s\n", name); + return 1; + } + /* Generate one, if it doesn't exist */ get_global_sam_sid(); if (!secrets_fetch_domain_sid(name, &sid)) { - DEBUG(0, ("Can't fetch domain SID for name: %s\n", name)); + DEBUG(0, ("Can't fetch domain SID for name: %s\n", name)); return 1; } sid_to_string(sid_str, &sid); @@ -459,12 +648,32 @@ static int net_setlocalsid(int argc, const char **argv) return 0; } +static int net_setdomainsid(int argc, const char **argv) +{ + DOM_SID sid; + + if ( (argc != 1) + || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0) + || (!string_to_sid(&sid, argv[0])) + || (sid.num_auths != 4)) { + d_printf("usage: net setdomainsid S-1-5-21-x-y-z\n"); + return 1; + } + + if (!secrets_store_domain_sid(lp_workgroup(), &sid)) { + DEBUG(0,("Can't store domain SID.\n")); + return 1; + } + + return 0; +} + static int net_getdomainsid(int argc, const char **argv) { DOM_SID domain_sid; fstring sid_str; - if(!initialize_password_db(False)) { + if(!initialize_password_db(False, NULL)) { DEBUG(0, ("WARNING: Could not open passdb - domain sid may not reflect passdb\n" "backend knowlege (such as the sid stored in LDAP)\n")); } @@ -473,14 +682,14 @@ static int net_getdomainsid(int argc, const char **argv) get_global_sam_sid(); if (!secrets_fetch_domain_sid(global_myname(), &domain_sid)) { - d_printf("Could not fetch local SID\n"); + d_fprintf(stderr, "Could not fetch local SID\n"); return 1; } sid_to_string(sid_str, &domain_sid); d_printf("SID for domain %s is: %s\n", global_myname(), sid_str); if (!secrets_fetch_domain_sid(opt_workgroup, &domain_sid)) { - d_printf("Could not fetch domain SID\n"); + d_fprintf(stderr, "Could not fetch domain SID\n"); return 1; } @@ -492,104 +701,118 @@ static int net_getdomainsid(int argc, const char **argv) #ifdef WITH_FAKE_KASERVER -int net_afskey_usage(int argc, const char **argv) +int net_help_afs(int argc, const char **argv) { - d_printf(" net afskey filename\n" + d_printf(" net afs key filename\n" "\tImports a OpenAFS KeyFile into our secrets.tdb\n\n"); + d_printf(" net afs impersonate \n" + "\tCreates a token for user@cell\n\n"); return -1; } -static int net_afskey(int argc, const char **argv) +static int net_afs_key(int argc, const char **argv) { int fd; struct afs_keyfile keyfile; if (argc != 2) { - d_printf("usage: 'net afskey cell'\n"); + d_printf("usage: 'net afs key cell'\n"); return -1; } if (!secrets_init()) { - d_printf("Could not open secrets.tdb\n"); + d_fprintf(stderr, "Could not open secrets.tdb\n"); return -1; } if ((fd = open(argv[0], O_RDONLY, 0)) < 0) { - d_printf("Could not open %s\n", argv[0]); + d_fprintf(stderr, "Could not open %s\n", argv[0]); return -1; } if (read(fd, &keyfile, sizeof(keyfile)) != sizeof(keyfile)) { - d_printf("Could not read keyfile\n"); + d_fprintf(stderr, "Could not read keyfile\n"); return -1; } if (!secrets_store_afs_keyfile(argv[1], &keyfile)) { - d_printf("Could not write keyfile to secrets.tdb\n"); + d_fprintf(stderr, "Could not write keyfile to secrets.tdb\n"); return -1; } return 0; } -#endif /* WITH_FAKE_KASERVER */ - -static uint32 get_maxrid(void) +static int net_afs_impersonate(int argc, const char **argv) { - SAM_ACCOUNT *pwd = NULL; - uint32 max_rid = 0; - GROUP_MAP *map = NULL; - int num_entries = 0; - int i; + char *token; - if (!pdb_setsampwent(False)) { - DEBUG(0, ("load_sampwd_entries: Unable to open passdb.\n")); - return 0; + if (argc != 2) { + fprintf(stderr, "Usage: net afs impersonate \n"); + exit(1); } - for (; (NT_STATUS_IS_OK(pdb_init_sam(&pwd))) - && pdb_getsampwent(pwd) == True; pwd=NULL) { - uint32 rid; - - if (!sid_peek_rid(pdb_get_user_sid(pwd), &rid)) { - DEBUG(0, ("can't get RID for user '%s'\n", - pdb_get_username(pwd))); - pdb_free_sam(&pwd); - continue; - } + token = afs_createtoken_str(argv[0], argv[1]); - if (rid > max_rid) - max_rid = rid; + if (token == NULL) { + fprintf(stderr, "Could not create token\n"); + exit(1); + } - DEBUG(1,("%d is user '%s'\n", rid, pdb_get_username(pwd))); - pdb_free_sam(&pwd); + if (!afs_settoken_str(token)) { + fprintf(stderr, "Could not set token into kernel\n"); + exit(1); } - pdb_endsampwent(); - pdb_free_sam(&pwd); + printf("Success: %s@%s\n", argv[0], argv[1]); + return 0; +} - if (!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, - ENUM_ONLY_MAPPED)) - return max_rid; +static int net_afs(int argc, const char **argv) +{ + struct functable func[] = { + {"key", net_afs_key}, + {"impersonate", net_afs_impersonate}, + {"help", net_help_afs}, + {NULL, NULL} + }; + return net_run_function(argc, argv, func, net_help_afs); +} - for (i = 0; i < num_entries; i++) { - uint32 rid; +#endif /* WITH_FAKE_KASERVER */ - if (!sid_peek_check_rid(get_global_sam_sid(), &map[i].sid, - &rid)) { - DEBUG(3, ("skipping map for group '%s', SID %s\n", - map[i].nt_name, - sid_string_static(&map[i].sid))); - continue; - } - DEBUG(1,("%d is group '%s'\n", rid, map[i].nt_name)); +static BOOL search_maxrid(struct pdb_search *search, const char *type, + uint32 *max_rid) +{ + struct samr_displayentry *entries; + uint32 i, num_entries; - if (rid > max_rid) - max_rid = rid; + if (search == NULL) { + d_fprintf(stderr, "get_maxrid: Could not search %s\n", type); + return False; } - SAFE_FREE(map); + num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries); + for (i=0; i