diff options
Diffstat (limited to 'source3/utils/smbtree.c')
-rw-r--r-- | source3/utils/smbtree.c | 191 |
1 files changed, 161 insertions, 30 deletions
diff --git a/source3/utils/smbtree.c b/source3/utils/smbtree.c index cbe1bd448f..940120d644 100644 --- a/source3/utils/smbtree.c +++ b/source3/utils/smbtree.c @@ -3,7 +3,6 @@ Network neighbourhood browser. Copyright (C) Tim Potter 2000 - Copyright (C) Jelmer Vernooij 2003 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 @@ -24,11 +23,34 @@ static BOOL use_bcast; +struct user_auth_info { + pstring username; + pstring password; + pstring workgroup; +}; + /* How low can we go? */ enum tree_level {LEV_WORKGROUP, LEV_SERVER, LEV_SHARE}; static enum tree_level level = LEV_SHARE; +static void usage(void) +{ + printf( +"Usage: smbtree [options]\n\ +\n\ +\t-d debuglevel set debug output level\n\ +\t-U username user to autheticate as\n\ +\t-W workgroup workgroup of user to authenticate as\n\ +\t-D list only domains (workgroups) of tree\n\ +\t-S list domains and servers of tree\n\ +\t-b use bcast instead of using the master browser\n\ +\n\ +The username can be of the form username%%password or\n\ +workgroup\\username%%password.\n\n\ +"); +} + /* Holds a list of workgroups or servers */ struct name_list { @@ -65,6 +87,62 @@ static void add_name(const char *machine_name, uint32 server_type, DLIST_ADD(*name_list, new_name); } +/* Return a cli_state pointing at the IPC$ share for the given server */ + +static struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip, + struct user_auth_info *user_info) +{ + struct cli_state *cli; + pstring myname; + NTSTATUS nt_status; + + get_myname(myname); + + nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC", + user_info->username, lp_workgroup(), user_info->password, + CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, NULL); + + if (NT_STATUS_IS_OK(nt_status)) { + return cli; + } else { + return NULL; + } +} + +/* Return the IP address and workgroup of a master browser on the + network. */ + +static BOOL find_master_ip_bcast(pstring workgroup, struct in_addr *server_ip) +{ + struct in_addr *ip_list; + int i, count; + + /* Go looking for workgroups by broadcasting on the local network */ + + if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) { + return False; + } + + for (i = 0; i < count; i++) { + static fstring name; + + if (!name_status_find("*", 0, 0x1d, ip_list[i], name)) + continue; + + if (!find_master_ip(name, server_ip)) + continue; + + pstrcpy(workgroup, name); + + DEBUG(4, ("found master browser %s, %s\n", + name, inet_ntoa(ip_list[i]))); + + return True; + } + + return False; +} + /**************************************************************************** display tree of smb workgroups, servers and shares ****************************************************************************/ @@ -80,21 +158,19 @@ static BOOL get_workgroups(struct user_auth_info *user_info) pstrcpy(master_workgroup, lp_workgroup()); - if (!use_bcast && !find_master_ip(lp_workgroup(), &server_ip)) { - DEBUG(4, ("Unable to find master browser for workgroup %s, falling back to broadcast\n", + if (use_bcast || !find_master_ip(lp_workgroup(), &server_ip)) { + DEBUG(4, ("Unable to find master browser for workgroup %s\n", master_workgroup)); - use_bcast = True; - } else if(!use_bcast) { - if (!(cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info))) - return False; - } - - if (!(cli = get_ipc_connect_master_ip_bcast(master_workgroup, user_info))) { + if (!find_master_ip_bcast(master_workgroup, &server_ip)) { DEBUG(4, ("Unable to find master browser by " "broadcast\n")); return False; + } } + if (!(cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info))) + return False; + if (!cli_NetServerEnum(cli, master_workgroup, SV_TYPE_DOMAIN_ENUM, add_name, &workgroups)) return False; @@ -191,17 +267,13 @@ static BOOL print_tree(struct user_auth_info *user_info) ****************************************************************************/ int main(int argc,char *argv[]) { - struct poptOption long_options[] = { - POPT_AUTOHELP - { "broadcast", 'b', POPT_ARG_VAL, &use_bcast, True, "Use broadcast instead of using the master browser" }, - { "domains", 'D', POPT_ARG_VAL, &level, LEV_WORKGROUP, "List only domains (workgroups) of tree" }, - { "servers", 'S', POPT_ARG_VAL, &level, LEV_SERVER, "List domains(workgroups) and servers of tree" }, - POPT_COMMON_SAMBA - POPT_COMMON_CREDENTIALS - POPT_TABLEEND - }; - poptContext pc; - + extern char *optarg; + extern int optind; + int opt; + char *p; + struct user_auth_info user_info; + BOOL got_pass = False; + /* Initialise samba stuff */ setlinebuf(stdout); @@ -210,27 +282,86 @@ static BOOL print_tree(struct user_auth_info *user_info) setup_logging(argv[0],True); - pc = poptGetContext("smbtree", argc, (const char **)argv, long_options, - POPT_CONTEXT_KEEP_FIRST); - while(poptGetNextOpt(pc) != -1); - poptFreeContext(pc); - lp_load(dyn_CONFIGFILE,True,False,False); load_interfaces(); + if (getenv("USER")) { + pstrcpy(user_info.username, getenv("USER")); + + if ((p=strchr(user_info.username, '%'))) { + *p = 0; + pstrcpy(user_info.password, p+1); + got_pass = True; + memset(strchr(getenv("USER"), '%') + 1, 'X', + strlen(user_info.password)); + } + } + + pstrcpy(user_info.workgroup, lp_workgroup()); + /* Parse command line args */ - if (!cmdline_auth_info.got_pass) { + while ((opt = getopt(argc, argv, "U:hd:W:DSb")) != EOF) { + switch (opt) { + case 'U': + pstrcpy(user_info.username,optarg); + p = strchr(user_info.username,'%'); + if (p) { + *p = 0; + pstrcpy(user_info.password, p+1); + got_pass = 1; + } + break; + + case 'b': + use_bcast = True; + break; + + case 'h': + usage(); + exit(1); + + case 'd': + DEBUGLEVEL = atoi(optarg); + break; + + case 'W': + pstrcpy(user_info.workgroup, optarg); + break; + + case 'D': + level = LEV_WORKGROUP; + break; + + case 'S': + level = LEV_SERVER; + break; + + default: + printf("Unknown option %c (%d)\n", (char)opt, opt); + exit(1); + } + } + + argc -= optind; + argv += optind; + + if (argc > 0) { + usage(); + exit(1); + } + + if (!got_pass) { char *pass = getpass("Password: "); if (pass) { - pstrcpy(cmdline_auth_info.password, pass); + pstrcpy(user_info.password, pass); } - cmdline_auth_info.got_pass = True; + got_pass = True; } /* Now do our stuff */ - if (!print_tree(&cmdline_auth_info)) + if (!print_tree(&user_info)) return 1; return 0; |