From fb1e289408cb8de4b8f9b988c56aa6d64df9b622 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Jul 2001 00:49:45 +0000 Subject: Syncup getting ready for release. Jeremy. --- source/libsmb/cli_lsarpc.c | 129 ++++++++------ source/libsmb/cli_samr.c | 405 ++++++++++++++++++++++++++++++++++++------- source/libsmb/cli_spoolss.c | 296 +++++++++++++++++++++---------- source/libsmb/cliconnect.c | 109 ++++++------ source/libsmb/clientgen.c | 14 +- source/libsmb/clierror.c | 3 +- source/libsmb/clifile.c | 216 ++++++++++++----------- source/libsmb/clilist.c | 146 +++++++++------- source/libsmb/climessage.c | 12 +- source/libsmb/clirap.c | 119 +++++++++---- source/libsmb/clireadwrite.c | 161 +++++++++-------- source/libsmb/clisecdesc.c | 13 +- source/libsmb/clitrans.c | 25 ++- source/libsmb/namequery.c | 151 +++++++++++++++- source/libsmb/pwd_cache.c | 10 ++ source/libsmb/smbdes.c | 2 +- source/libsmb/smbencrypt.c | 2 +- source/libsmb/unexpected.c | 4 +- 18 files changed, 1237 insertions(+), 580 deletions(-) (limited to 'source/libsmb') diff --git a/source/libsmb/cli_lsarpc.c b/source/libsmb/cli_lsarpc.c index 7f5431e4b3a..88f0dff225b 100644 --- a/source/libsmb/cli_lsarpc.c +++ b/source/libsmb/cli_lsarpc.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 2.2 RPC pipe client - Copyright (C) Tim Potter 2000, + Copyright (C) Tim Potter 2000-2001, Copyright (C) Andrew Tridgell 1992-1997,2000, Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000, Copyright (C) Paul Ashton 1997,2000, @@ -84,8 +84,8 @@ void cli_lsa_shutdown(struct cli_state *cli) /* Open a LSA policy handle */ -uint32 cli_lsa_open_policy(struct cli_state *cli, BOOL sec_qos, - uint32 des_access, POLICY_HND *pol) +uint32 cli_lsa_open_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx, + BOOL sec_qos, uint32 des_access, POLICY_HND *pol) { prs_struct qbuf, rbuf; LSA_Q_OPEN_POL q; @@ -98,8 +98,8 @@ uint32 cli_lsa_open_policy(struct cli_state *cli, BOOL sec_qos, /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Initialise input parameters */ @@ -140,7 +140,8 @@ uint32 cli_lsa_open_policy(struct cli_state *cli, BOOL sec_qos, /* Close a LSA policy handle */ -uint32 cli_lsa_close(struct cli_state *cli, POLICY_HND *pol) +uint32 cli_lsa_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol) { prs_struct qbuf, rbuf; LSA_Q_CLOSE q; @@ -152,8 +153,8 @@ uint32 cli_lsa_close(struct cli_state *cli, POLICY_HND *pol) /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -187,9 +188,9 @@ uint32 cli_lsa_close(struct cli_state *cli, POLICY_HND *pol) /* Lookup a list of sids */ -uint32 cli_lsa_lookup_sids(struct cli_state *cli, POLICY_HND *pol, - int num_sids, DOM_SID *sids, char ***names, - uint32 **types, int *num_names) +uint32 cli_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, int num_sids, DOM_SID *sids, + char ***names, uint32 **types, int *num_names) { prs_struct qbuf, rbuf; LSA_Q_LOOKUP_SIDS q; @@ -204,12 +205,12 @@ uint32 cli_lsa_lookup_sids(struct cli_state *cli, POLICY_HND *pol, /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ - init_q_lookup_sids(cli->mem_ctx, &q, pol, num_sids, sids, 1); + init_q_lookup_sids(mem_ctx, &q, pol, num_sids, sids, 1); if (!lsa_io_q_lookup_sids("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, LSA_LOOKUPSIDS, &qbuf, &rbuf)) { @@ -246,14 +247,14 @@ uint32 cli_lsa_lookup_sids(struct cli_state *cli, POLICY_HND *pol, (*num_names) = r.names->num_entries; - if (!((*names) = (char **)malloc(sizeof(char *) * + if (!((*names) = (char **)talloc(mem_ctx, sizeof(char *) * r.names->num_entries))) { DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n")); result = NT_STATUS_UNSUCCESSFUL; goto done; } - if (!((*types) = (uint32 *)malloc(sizeof(uint32) * + if (!((*types) = (uint32 *)talloc(mem_ctx, sizeof(uint32) * r.names->num_entries))) { DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n")); result = NT_STATUS_UNSUCCESSFUL; @@ -277,7 +278,7 @@ uint32 cli_lsa_lookup_sids(struct cli_state *cli, POLICY_HND *pol, "%s%s%s", dom_name, dom_name[0] ? "\\" : "", name); - (*names)[i] = strdup(full_name); + (*names)[i] = talloc_strdup(mem_ctx, full_name); (*types)[i] = t_names.name[i].sid_name_use; } else { (*names)[i] = NULL; @@ -294,9 +295,9 @@ uint32 cli_lsa_lookup_sids(struct cli_state *cli, POLICY_HND *pol, /* Lookup a list of names */ -uint32 cli_lsa_lookup_names(struct cli_state *cli, POLICY_HND *pol, - int num_names, char **names, DOM_SID **sids, - uint32 **types, int *num_sids) +uint32 cli_lsa_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, int num_names, char **names, + DOM_SID **sids, uint32 **types, int *num_sids) { prs_struct qbuf, rbuf; LSA_Q_LOOKUP_NAMES q; @@ -310,12 +311,12 @@ uint32 cli_lsa_lookup_names(struct cli_state *cli, POLICY_HND *pol, /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ - init_q_lookup_names(cli->mem_ctx, &q, pol, num_names, names); + init_q_lookup_names(mem_ctx, &q, pol, num_names, names); if (!lsa_io_q_lookup_names("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, LSA_LOOKUPNAMES, &qbuf, &rbuf)) { @@ -349,14 +350,14 @@ uint32 cli_lsa_lookup_names(struct cli_state *cli, POLICY_HND *pol, (*num_sids) = r.num_entries; - if (!((*sids = (DOM_SID *)malloc(sizeof(DOM_SID) * + if (!((*sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) * r.num_entries)))) { DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n")); result = NT_STATUS_UNSUCCESSFUL; goto done; } - if (!((*types = (uint32 *)malloc(sizeof(uint32) * + if (!((*types = (uint32 *)talloc(mem_ctx, sizeof(uint32) * r.num_entries)))) { DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n")); result = NT_STATUS_UNSUCCESSFUL; @@ -395,9 +396,9 @@ uint32 cli_lsa_lookup_names(struct cli_state *cli, POLICY_HND *pol, /* Query info policy */ -uint32 cli_lsa_query_info_policy(struct cli_state *cli, POLICY_HND *pol, - uint16 info_class, fstring domain_name, - DOM_SID * domain_sid) +uint32 cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint16 info_class, + fstring domain_name, DOM_SID *domain_sid) { prs_struct qbuf, rbuf; LSA_Q_QUERY_INFO q; @@ -409,8 +410,8 @@ uint32 cli_lsa_query_info_policy(struct cli_state *cli, POLICY_HND *pol, /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -435,6 +436,9 @@ uint32 cli_lsa_query_info_policy(struct cli_state *cli, POLICY_HND *pol, /* Return output parameters */ + ZERO_STRUCTP(domain_sid); + domain_name[0] = '\0'; + switch (info_class) { case 3: @@ -479,9 +483,10 @@ uint32 cli_lsa_query_info_policy(struct cli_state *cli, POLICY_HND *pol, /* Enumerate list of trusted domains */ -uint32 cli_lsa_enum_trust_dom(struct cli_state *cli, POLICY_HND *pol, - uint32 *enum_ctx, uint32 *num_domains, - char ***domain_names, DOM_SID **domain_sids) +uint32 cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 *enum_ctx, + uint32 *num_domains, char ***domain_names, + DOM_SID **domain_sids) { prs_struct qbuf, rbuf; LSA_Q_ENUM_TRUST_DOM q; @@ -494,8 +499,8 @@ uint32 cli_lsa_enum_trust_dom(struct cli_state *cli, POLICY_HND *pol, /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -516,7 +521,12 @@ uint32 cli_lsa_enum_trust_dom(struct cli_state *cli, POLICY_HND *pol, result = r.status; - if (result != NT_STATUS_NOPROBLEMO && result != 0x8000001a) { + /* For some undocumented reason this function sometimes returns + 0x8000001a (NT_STATUS_UNABLE_TO_FREE_VM) so we ignore it and + pretend everything is OK. */ + + if (result != NT_STATUS_NOPROBLEMO && + result != NT_STATUS_UNABLE_TO_FREE_VM) { /* An actual error ocured */ @@ -527,33 +537,42 @@ uint32 cli_lsa_enum_trust_dom(struct cli_state *cli, POLICY_HND *pol, /* Return output parameters */ - if (!((*domain_names) = (char **)malloc(sizeof(char *) * - r.num_domains))) { - DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n")); - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + if (r.num_domains) { - if (!((*domain_sids) = (DOM_SID *)malloc(sizeof(DOM_SID) * - r.num_domains))) { - DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n")); - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + /* Allocate memory for trusted domain names and sids */ - for (i = 0; i < r.num_domains; i++) { - fstring tmp; + *domain_names = (char **)talloc(mem_ctx, sizeof(char *) * + r.num_domains); - unistr2_to_ascii(tmp, &r.uni_domain_name[i], sizeof(tmp) - 1); - (*domain_names)[i] = strdup(tmp); - sid_copy(&(*domain_sids)[i], &r.domain_sid[i].sid); + if (!*domain_names) { + DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n")); + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + *domain_sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) * + r.num_domains); + if (!domain_sids) { + DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n")); + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Copy across names and sids */ + + for (i = 0; i < r.num_domains; i++) { + fstring tmp; + + unistr2_to_ascii(tmp, &r.uni_domain_name[i], + sizeof(tmp) - 1); + (*domain_names)[i] = strdup(tmp); + sid_copy(&(*domain_sids)[i], &r.domain_sid[i].sid); + } } *num_domains = r.num_domains; *enum_ctx = r.enum_context; - lsa_free_r_enum_trust_dom(&r); - done: prs_mem_free(&qbuf); prs_mem_free(&rbuf); diff --git a/source/libsmb/cli_samr.c b/source/libsmb/cli_samr.c index 4c53bd05847..9fb7e078f67 100644 --- a/source/libsmb/cli_samr.c +++ b/source/libsmb/cli_samr.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 2.2 RPC pipe client - Copyright (C) Tim Potter 2000, + Copyright (C) Tim Potter 2000-2001, Copyright (C) Andrew Tridgell 1992-1997,2000, Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000, Copyright (C) Paul Ashton 1997,2000, @@ -84,21 +84,22 @@ void cli_samr_shutdown(struct cli_state *cli) /* Connect to SAMR database */ -uint32 cli_samr_connect(struct cli_state *cli, char *srv_name, - uint32 access_mask, POLICY_HND *connect_pol) +uint32 cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, + char *srv_name, uint32 access_mask, + POLICY_HND *connect_pol) { prs_struct qbuf, rbuf; SAMR_Q_CONNECT q; SAMR_R_CONNECT r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -106,14 +107,12 @@ uint32 cli_samr_connect(struct cli_state *cli, char *srv_name, if (!samr_io_q_connect("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_CONNECT, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } /* Unmarshall response */ if (!samr_io_r_connect("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -132,20 +131,21 @@ uint32 cli_samr_connect(struct cli_state *cli, char *srv_name, /* Close SAMR handle */ -uint32 cli_samr_close(struct cli_state *cli, POLICY_HND *connect_pol) +uint32 cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *connect_pol) { prs_struct qbuf, rbuf; SAMR_Q_CLOSE_HND q; SAMR_R_CLOSE_HND r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -153,14 +153,12 @@ uint32 cli_samr_close(struct cli_state *cli, POLICY_HND *connect_pol) if (!samr_io_q_close_hnd("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } /* Unmarshall response */ if (!samr_io_r_close_hnd("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -179,22 +177,22 @@ uint32 cli_samr_close(struct cli_state *cli, POLICY_HND *connect_pol) /* Open handle on a domain */ -uint32 cli_samr_open_domain(struct cli_state *cli, POLICY_HND *connect_pol, - uint32 access_mask, DOM_SID *domain_sid, - POLICY_HND *domain_pol) +uint32 cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *connect_pol, uint32 access_mask, + DOM_SID *domain_sid, POLICY_HND *domain_pol) { prs_struct qbuf, rbuf; SAMR_Q_OPEN_DOMAIN q; SAMR_R_OPEN_DOMAIN r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -202,14 +200,12 @@ uint32 cli_samr_open_domain(struct cli_state *cli, POLICY_HND *connect_pol, if (!samr_io_q_open_domain("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } /* Unmarshall response */ if (!samr_io_r_open_domain("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -228,22 +224,22 @@ uint32 cli_samr_open_domain(struct cli_state *cli, POLICY_HND *connect_pol, /* Open handle on a user */ -uint32 cli_samr_open_user(struct cli_state *cli, POLICY_HND *domain_pol, - uint32 access_mask, uint32 user_rid, - POLICY_HND *user_pol) +uint32 cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 access_mask, + uint32 user_rid, POLICY_HND *user_pol) { prs_struct qbuf, rbuf; SAMR_Q_OPEN_USER q; SAMR_R_OPEN_USER r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -251,14 +247,12 @@ uint32 cli_samr_open_user(struct cli_state *cli, POLICY_HND *domain_pol, if (!samr_io_q_open_user("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_OPEN_USER, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } /* Unmarshall response */ if (!samr_io_r_open_user("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -277,22 +271,22 @@ uint32 cli_samr_open_user(struct cli_state *cli, POLICY_HND *domain_pol, /* Open handle on a group */ -uint32 cli_samr_open_group(struct cli_state *cli, POLICY_HND *domain_pol, - uint32 access_mask, uint32 group_rid, - POLICY_HND *group_pol) +uint32 cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 access_mask, + uint32 group_rid, POLICY_HND *group_pol) { prs_struct qbuf, rbuf; SAMR_Q_OPEN_GROUP q; SAMR_R_OPEN_GROUP r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -300,14 +294,12 @@ uint32 cli_samr_open_group(struct cli_state *cli, POLICY_HND *domain_pol, if (!samr_io_q_open_group("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } /* Unmarshall response */ if (!samr_io_r_open_group("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -326,21 +318,22 @@ uint32 cli_samr_open_group(struct cli_state *cli, POLICY_HND *domain_pol, /* Query user info */ -uint32 cli_samr_query_userinfo(struct cli_state *cli, POLICY_HND *user_pol, - uint16 switch_value, SAM_USERINFO_CTR *ctr) +uint32 cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *user_pol, uint16 switch_value, + SAM_USERINFO_CTR *ctr) { prs_struct qbuf, rbuf; SAMR_Q_QUERY_USERINFO q; SAMR_R_QUERY_USERINFO r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -348,7 +341,6 @@ uint32 cli_samr_query_userinfo(struct cli_state *cli, POLICY_HND *user_pol, if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -357,7 +349,6 @@ uint32 cli_samr_query_userinfo(struct cli_state *cli, POLICY_HND *user_pol, r.ctr = ctr; if (!samr_io_r_query_userinfo("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -374,21 +365,22 @@ uint32 cli_samr_query_userinfo(struct cli_state *cli, POLICY_HND *user_pol, /* Query group info */ -uint32 cli_samr_query_groupinfo(struct cli_state *cli, POLICY_HND *group_pol, - uint32 info_level, GROUP_INFO_CTR *ctr) +uint32 cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *group_pol, uint32 info_level, + GROUP_INFO_CTR *ctr) { prs_struct qbuf, rbuf; SAMR_Q_QUERY_GROUPINFO q; SAMR_R_QUERY_GROUPINFO r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -396,7 +388,6 @@ uint32 cli_samr_query_groupinfo(struct cli_state *cli, POLICY_HND *group_pol, if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -405,7 +396,6 @@ uint32 cli_samr_query_groupinfo(struct cli_state *cli, POLICY_HND *group_pol, r.ctr = ctr; if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -422,21 +412,22 @@ uint32 cli_samr_query_groupinfo(struct cli_state *cli, POLICY_HND *group_pol, /* Query user groups */ -uint32 cli_samr_query_usergroups(struct cli_state *cli, POLICY_HND *user_pol, - uint32 *num_groups, DOM_GID **gid) +uint32 cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *user_pol, uint32 *num_groups, + DOM_GID **gid) { prs_struct qbuf, rbuf; SAMR_Q_QUERY_USERGROUPS q; SAMR_R_QUERY_USERGROUPS r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -444,14 +435,12 @@ uint32 cli_samr_query_usergroups(struct cli_state *cli, POLICY_HND *user_pol, if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } /* Unmarshall response */ if (!samr_io_r_query_usergroups("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -471,21 +460,22 @@ uint32 cli_samr_query_usergroups(struct cli_state *cli, POLICY_HND *user_pol, /* Query user groups */ -uint32 cli_samr_query_groupmem(struct cli_state *cli, POLICY_HND *group_pol, - uint32 *num_mem, uint32 **rid, uint32 **attr) +uint32 cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *group_pol, uint32 *num_mem, + uint32 **rid, uint32 **attr) { prs_struct qbuf, rbuf; SAMR_Q_QUERY_GROUPMEM q; SAMR_R_QUERY_GROUPMEM r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -493,14 +483,12 @@ uint32 cli_samr_query_groupmem(struct cli_state *cli, POLICY_HND *group_pol, if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } /* Unmarshall response */ if (!samr_io_r_query_groupmem("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -518,3 +506,288 @@ uint32 cli_samr_query_groupmem(struct cli_state *cli, POLICY_HND *group_pol, return result; } + +/* Enumerate domain groups */ + +uint32 cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 *start_idx, + uint32 size, struct acct_info **dom_groups, + uint32 *num_dom_groups) +{ + prs_struct qbuf, rbuf; + SAMR_Q_ENUM_DOM_GROUPS q; + SAMR_R_ENUM_DOM_GROUPS r; + uint32 result = NT_STATUS_UNSUCCESSFUL, name_idx, i; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_samr_q_enum_dom_groups(&q, pol, *start_idx, size); + + if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf)) { + goto done; + } + + /* Unmarshall response */ + + if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0)) { + goto done; + } + + /* Return output parameters */ + + result = r.status; + + if (result != NT_STATUS_NOPROBLEMO && + result != STATUS_MORE_ENTRIES) { + goto done; + } + + *num_dom_groups = r.num_entries2; + + if (!((*dom_groups) = (struct acct_info *) + talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + memset(*dom_groups, 0, sizeof(struct acct_info) * *num_dom_groups); + + name_idx = 0; + + for (i = 0; i < *num_dom_groups; i++) { + + (*dom_groups)[i].rid = r.sam[i].rid; + + if (r.sam[i].hdr_name.buffer) { + unistr2_to_ascii((*dom_groups)[i].acct_name, + &r.uni_grp_name[name_idx], + sizeof(fstring) - 1); + name_idx++; + } + + *start_idx = r.next_idx; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Query alias members */ + +uint32 cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *alias_pol, uint32 *num_mem, + DOM_SID **sids) +{ + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_ALIASMEM q; + SAMR_R_QUERY_ALIASMEM r; + uint32 result = NT_STATUS_UNSUCCESSFUL, i; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_samr_q_query_aliasmem(&q, alias_pol); + + if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) { + goto done; + } + + /* Unmarshall response */ + + if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) { + goto done; + } + + /* Return output parameters */ + + if ((result = r.status) != NT_STATUS_NOPROBLEMO) { + goto done; + } + + *num_mem = r.num_sids; + + if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + for (i = 0; i < *num_mem; i++) { + (*sids)[i] = r.sid[i].sid; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Open handle on an alias */ + +uint32 cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 access_mask, + uint32 alias_rid, POLICY_HND *alias_pol) +{ + prs_struct qbuf, rbuf; + SAMR_Q_OPEN_ALIAS q; + SAMR_R_OPEN_ALIAS r; + uint32 result; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_samr_q_open_alias(&q, domain_pol, access_mask, alias_rid); + + if (!samr_io_q_open_alias("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!samr_io_r_open_alias("", &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Return output parameters */ + + if ((result = r.status) == NT_STATUS_NOPROBLEMO) { + *alias_pol = r.pol; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Query domain info */ + +uint32 cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint16 switch_value, + SAM_UNK_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_DOMAIN_INFO q; + SAMR_R_QUERY_DOMAIN_INFO r; + uint32 result = NT_STATUS_UNSUCCESSFUL; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_samr_q_query_dom_info(&q, domain_pol, switch_value); + + if (!samr_io_q_query_dom_info("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &qbuf, &rbuf)) { + goto done; + } + + /* Unmarshall response */ + + r.ctr = ctr; + + if (!samr_io_r_query_dom_info("", &r, &rbuf, 0)) { + goto done; + } + + /* Return output parameters */ + + if ((result = r.status) != NT_STATUS_NOPROBLEMO) { + goto done; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Query display info */ + +uint32 cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 *start_idx, + uint16 switch_value, uint32 *num_entries, + uint32 max_entries, SAM_DISPINFO_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_DISPINFO q; + SAMR_R_QUERY_DISPINFO r; + uint32 result = NT_STATUS_UNSUCCESSFUL; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_samr_q_query_dispinfo(&q, domain_pol, switch_value, + *start_idx, max_entries); + + if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) { + goto done; + } + + /* Unmarshall response */ + + if (!samr_io_r_query_dispinfo("", &r, &rbuf, 0)) { + goto done; + } + + /* Return output parameters */ + + if ((result = r.status) != NT_STATUS_NOPROBLEMO) { + goto done; + } + + *num_entries = r.num_entries; + *start_idx += r.num_entries; /* No next_idx in this structure! */ + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} diff --git a/source/libsmb/cli_spoolss.c b/source/libsmb/cli_spoolss.c index db761e57bfa..2c962ef27a0 100644 --- a/source/libsmb/cli_spoolss.c +++ b/source/libsmb/cli_spoolss.c @@ -87,10 +87,16 @@ void cli_spoolss_shutdown(struct cli_state *cli) /* Open printer ex */ -uint32 cli_spoolss_open_printer_ex(struct cli_state *cli, char *printername, - char *datatype, uint32 access_required, - char *station, char *username, - POLICY_HND *pol) +uint32 cli_spoolss_open_printer_ex( + struct cli_state *cli, + TALLOC_CTX *mem_ctx, + char *printername, + char *datatype, + uint32 access_required, + char *station, + char *username, + POLICY_HND *pol +) { prs_struct qbuf, rbuf; SPOOL_Q_OPEN_PRINTER_EX q; @@ -102,8 +108,8 @@ uint32 cli_spoolss_open_printer_ex(struct cli_state *cli, char *printername, /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Initialise input parameters */ @@ -140,7 +146,11 @@ uint32 cli_spoolss_open_printer_ex(struct cli_state *cli, char *printername, /* Close a printer handle */ -uint32 cli_spoolss_close_printer(struct cli_state *cli, POLICY_HND *pol) +uint32 cli_spoolss_close_printer( + struct cli_state *cli, + TALLOC_CTX *mem_ctx, + POLICY_HND *pol +) { prs_struct qbuf, rbuf; SPOOL_Q_CLOSEPRINTER q; @@ -152,8 +162,8 @@ uint32 cli_spoolss_close_printer(struct cli_state *cli, POLICY_HND *pol) /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Initialise input parameters */ @@ -201,8 +211,12 @@ static void init_buffer(NEW_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx) /* Decode various printer info levels - perhaps this should live in parse_spoolss.c? */ -static void decode_printer_info_0(NEW_BUFFER *buffer, uint32 returned, - PRINTER_INFO_0 **info) +static void decode_printer_info_0( + TALLOC_CTX *mem_ctx, + NEW_BUFFER *buffer, + uint32 returned, + PRINTER_INFO_0 **info +) { uint32 i; PRINTER_INFO_0 *inf; @@ -218,13 +232,17 @@ static void decode_printer_info_0(NEW_BUFFER *buffer, uint32 returned, *info=inf; } -static void decode_printer_info_1(NEW_BUFFER *buffer, uint32 returned, - PRINTER_INFO_1 **info) +static void decode_printer_info_1( + TALLOC_CTX *mem_ctx, + NEW_BUFFER *buffer, + uint32 returned, + PRINTER_INFO_1 **info +) { uint32 i; PRINTER_INFO_1 *inf; - inf=(PRINTER_INFO_1 *)malloc(returned*sizeof(PRINTER_INFO_1)); + inf=(PRINTER_INFO_1 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_1)); buffer->prs.data_offset=0; @@ -235,13 +253,17 @@ static void decode_printer_info_1(NEW_BUFFER *buffer, uint32 returned, *info=inf; } -static void decode_printer_info_2(NEW_BUFFER *buffer, uint32 returned, - PRINTER_INFO_2 **info) +static void decode_printer_info_2( + TALLOC_CTX *mem_ctx, + NEW_BUFFER *buffer, + uint32 returned, + PRINTER_INFO_2 **info +) { uint32 i; PRINTER_INFO_2 *inf; - inf=(PRINTER_INFO_2 *)malloc(returned*sizeof(PRINTER_INFO_2)); + inf=(PRINTER_INFO_2 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_2)); buffer->prs.data_offset=0; @@ -254,13 +276,17 @@ static void decode_printer_info_2(NEW_BUFFER *buffer, uint32 returned, *info=inf; } -static void decode_printer_info_3(NEW_BUFFER *buffer, uint32 returned, - PRINTER_INFO_3 **info) +static void decode_printer_info_3( + TALLOC_CTX *mem_ctx, + NEW_BUFFER *buffer, + uint32 returned, + PRINTER_INFO_3 **info +) { uint32 i; PRINTER_INFO_3 *inf; - inf=(PRINTER_INFO_3 *)malloc(returned*sizeof(PRINTER_INFO_3)); + inf=(PRINTER_INFO_3 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_3)); buffer->prs.data_offset=0; @@ -275,13 +301,17 @@ static void decode_printer_info_3(NEW_BUFFER *buffer, uint32 returned, /********************************************************************** Decode a PORT_INFO_1 struct from a NEW_BUFFER **********************************************************************/ -static void decode_port_info_1(NEW_BUFFER *buffer, uint32 returned, - PORT_INFO_1 **info) +static void decode_port_info_1( + TALLOC_CTX *mem_ctx, + NEW_BUFFER *buffer, + uint32 returned, + PORT_INFO_1 **info +) { uint32 i; PORT_INFO_1 *inf; - inf=(PORT_INFO_1*)malloc(returned*sizeof(PORT_INFO_1)); + inf=(PORT_INFO_1*)talloc(mem_ctx, returned*sizeof(PORT_INFO_1)); prs_set_offset(&buffer->prs, 0); @@ -295,13 +325,16 @@ static void decode_port_info_1(NEW_BUFFER *buffer, uint32 returned, /********************************************************************** Decode a PORT_INFO_2 struct from a NEW_BUFFER **********************************************************************/ -static void decode_port_info_2(NEW_BUFFER *buffer, uint32 returned, - PORT_INFO_2 **info) +static void decode_port_info_2( + TALLOC_CTX *mem_ctx, + NEW_BUFFER *buffer, + uint32 returned, + PORT_INFO_2 **info) { uint32 i; PORT_INFO_2 *inf; - inf=(PORT_INFO_2*)malloc(returned*sizeof(PORT_INFO_2)); + inf=(PORT_INFO_2*)talloc(mem_ctx, returned*sizeof(PORT_INFO_2)); prs_set_offset(&buffer->prs, 0); @@ -312,13 +345,17 @@ static void decode_port_info_2(NEW_BUFFER *buffer, uint32 returned, *info=inf; } -static void decode_printer_driver_1(NEW_BUFFER *buffer, uint32 returned, - DRIVER_INFO_1 **info) +static void decode_printer_driver_1( + TALLOC_CTX *mem_ctx, + NEW_BUFFER *buffer, + uint32 returned, + DRIVER_INFO_1 **info +) { uint32 i; DRIVER_INFO_1 *inf; - inf=(DRIVER_INFO_1 *)malloc(returned*sizeof(DRIVER_INFO_1)); + inf=(DRIVER_INFO_1 *)talloc(mem_ctx, returned*sizeof(DRIVER_INFO_1)); buffer->prs.data_offset=0; @@ -329,13 +366,17 @@ static void decode_printer_driver_1(NEW_BUFFER *buffer, uint32 returned, *info=inf; } -static void decode_printer_driver_2(NEW_BUFFER *buffer, uint32 returned, - DRIVER_INFO_2 **info) +static void decode_printer_driver_2( + TALLOC_CTX *mem_ctx, + NEW_BUFFER *buffer, + uint32 returned, + DRIVER_INFO_2 **info +) { uint32 i; DRIVER_INFO_2 *inf; - inf=(DRIVER_INFO_2 *)malloc(returned*sizeof(DRIVER_INFO_2)); + inf=(DRIVER_INFO_2 *)talloc(mem_ctx, returned*sizeof(DRIVER_INFO_2)); buffer->prs.data_offset=0; @@ -347,6 +388,7 @@ static void decode_printer_driver_2(NEW_BUFFER *buffer, uint32 returned, } static void decode_printer_driver_3( + TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, uint32 returned, DRIVER_INFO_3 **info @@ -355,7 +397,7 @@ static void decode_printer_driver_3( uint32 i; DRIVER_INFO_3 *inf; - inf=(DRIVER_INFO_3 *)malloc(returned*sizeof(DRIVER_INFO_3)); + inf=(DRIVER_INFO_3 *)talloc(mem_ctx, returned*sizeof(DRIVER_INFO_3)); buffer->prs.data_offset=0; @@ -367,6 +409,7 @@ static void decode_printer_driver_3( } static void decode_printerdriverdir_1 ( + TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, uint32 returned, DRIVER_DIRECTORY_1 **info @@ -374,7 +417,7 @@ static void decode_printerdriverdir_1 ( { DRIVER_DIRECTORY_1 *inf; - inf=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1)); + inf=(DRIVER_DIRECTORY_1 *)talloc(mem_ctx, sizeof(DRIVER_DIRECTORY_1)); prs_set_offset(&buffer->prs, 0); @@ -386,9 +429,14 @@ static void decode_printerdriverdir_1 ( /* Enumerate printers */ -uint32 cli_spoolss_enum_printers(struct cli_state *cli, uint32 flags, - uint32 level, int *returned, - PRINTER_INFO_CTR *ctr) +uint32 cli_spoolss_enum_printers( + struct cli_state *cli, + TALLOC_CTX *mem_ctx, + uint32 flags, + uint32 level, + int *returned, + PRINTER_INFO_CTR *ctr +) { prs_struct qbuf, rbuf; SPOOL_Q_ENUMPRINTERS q; @@ -407,10 +455,10 @@ uint32 cli_spoolss_enum_printers(struct cli_state *cli, uint32 flags, do { /* Initialise input parameters */ - init_buffer(&buffer, needed, cli->mem_ctx); + init_buffer(&buffer, needed, mem_ctx); - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); make_spoolss_q_enumprinters(&q, flags, server, level, &buffer, needed); @@ -430,21 +478,20 @@ uint32 cli_spoolss_enum_printers(struct cli_state *cli, uint32 flags, /* Return output parameters */ - if ((result = r.status) == NT_STATUS_NOPROBLEMO && r.returned > 0) { - - *returned = r.returned; + if (((result=r.status) == NT_STATUS_NOPROBLEMO) && (*returned = r.returned)) + { switch (level) { case 1: - decode_printer_info_1(r.buffer, r.returned, + decode_printer_info_1(mem_ctx, r.buffer, r.returned, &ctr->printers_1); break; case 2: - decode_printer_info_2(r.buffer, r.returned, + decode_printer_info_2(mem_ctx, r.buffer, r.returned, &ctr->printers_2); break; case 3: - decode_printer_info_3(r.buffer, r.returned, + decode_printer_info_3(mem_ctx, r.buffer, r.returned, &ctr->printers_3); break; } @@ -460,8 +507,13 @@ uint32 cli_spoolss_enum_printers(struct cli_state *cli, uint32 flags, } /* Enumerate printer ports */ -uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level, - int *returned, PORT_INFO_CTR *ctr) +uint32 cli_spoolss_enum_ports( + struct cli_state *cli, + TALLOC_CTX *mem_ctx, + uint32 level, + int *returned, + PORT_INFO_CTR *ctr +) { prs_struct qbuf, rbuf; SPOOL_Q_ENUMPORTS q; @@ -480,10 +532,10 @@ uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level, do { /* Initialise input parameters */ - init_buffer(&buffer, needed, cli->mem_ctx); + init_buffer(&buffer, needed, mem_ctx); - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); make_spoolss_q_enumports(&q, server, level, &buffer, needed); @@ -509,11 +561,11 @@ uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level, switch (level) { case 1: - decode_port_info_1(r.buffer, r.returned, + decode_port_info_1(mem_ctx, r.buffer, r.returned, &ctr->port.info_1); break; case 2: - decode_port_info_2(r.buffer, r.returned, + decode_port_info_2(mem_ctx, r.buffer, r.returned, &ctr->port.info_2); break; } @@ -531,6 +583,7 @@ uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level, /* Get printer info */ uint32 cli_spoolss_getprinter( struct cli_state *cli, + TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 level, PRINTER_INFO_CTR *ctr @@ -549,12 +602,12 @@ uint32 cli_spoolss_getprinter( do { /* Initialise input parameters */ - init_buffer(&buffer, needed, cli->mem_ctx); + init_buffer(&buffer, needed, mem_ctx); - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - make_spoolss_q_getprinter(&q, pol, level, &buffer, needed); + make_spoolss_q_getprinter(mem_ctx, &q, pol, level, &buffer, needed); /* Marshall data and send request */ if (!spoolss_io_q_getprinter("", &q, &qbuf, 0) || @@ -574,16 +627,16 @@ uint32 cli_spoolss_getprinter( switch (level) { case 0: - decode_printer_info_0(r.buffer, 1, &ctr->printers_0); + decode_printer_info_0(mem_ctx, r.buffer, 1, &ctr->printers_0); break; case 1: - decode_printer_info_1(r.buffer, 1, &ctr->printers_1); + decode_printer_info_1(mem_ctx, r.buffer, 1, &ctr->printers_1); break; case 2: - decode_printer_info_2(r.buffer, 1, &ctr->printers_2); + decode_printer_info_2(mem_ctx, r.buffer, 1, &ctr->printers_2); break; case 3: - decode_printer_info_3(r.buffer, 1, &ctr->printers_3); + decode_printer_info_3(mem_ctx, r.buffer, 1, &ctr->printers_3); break; } } @@ -602,6 +655,7 @@ uint32 cli_spoolss_getprinter( */ uint32 cli_spoolss_setprinter( struct cli_state *cli, + TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 level, PRINTER_INFO_CTR *ctr, @@ -617,13 +671,12 @@ uint32 cli_spoolss_setprinter( ZERO_STRUCT(r); /* Initialise input parameters */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - make_spoolss_q_setprinter(&q, pol, level, ctr, command); + make_spoolss_q_setprinter(mem_ctx, &q, pol, level, ctr, command); /* Marshall data and send request */ - result = NT_STATUS_UNSUCCESSFUL; if (!spoolss_io_q_setprinter("", &q, &qbuf, 0) || !rpc_api_pipe_req(cli, SPOOLSS_SETPRINTER, &qbuf, &rbuf)) { @@ -632,7 +685,6 @@ uint32 cli_spoolss_setprinter( } /* Unmarshall response */ - result = NT_STATUS_UNSUCCESSFUL; if (!spoolss_io_r_setprinter("", &r, &rbuf, 0)) { goto done; @@ -653,6 +705,7 @@ done: */ uint32 cli_spoolss_getprinterdriver ( struct cli_state *cli, + TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 level, char* env, @@ -677,10 +730,10 @@ uint32 cli_spoolss_getprinterdriver ( { /* Initialise input parameters */ - init_buffer(&buffer, needed, cli->mem_ctx); + init_buffer(&buffer, needed, mem_ctx); - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* write the request */ @@ -707,13 +760,13 @@ uint32 cli_spoolss_getprinterdriver ( switch (level) { case 1: - decode_printer_driver_1(r.buffer, 1, &ctr->info1); + decode_printer_driver_1(mem_ctx, r.buffer, 1, &ctr->info1); break; case 2: - decode_printer_driver_2(r.buffer, 1, &ctr->info2); + decode_printer_driver_2(mem_ctx, r.buffer, 1, &ctr->info2); break; case 3: - decode_printer_driver_3(r.buffer, 1, &ctr->info3); + decode_printer_driver_3(mem_ctx, r.buffer, 1, &ctr->info3); break; } } @@ -732,6 +785,7 @@ uint32 cli_spoolss_getprinterdriver ( */ uint32 cli_spoolss_enumprinterdrivers ( struct cli_state *cli, + TALLOC_CTX *mem_ctx, uint32 level, char* env, uint32 *returned, @@ -755,10 +809,10 @@ uint32 cli_spoolss_enumprinterdrivers ( do { /* Initialise input parameters */ - init_buffer(&buffer, needed, cli->mem_ctx); + init_buffer(&buffer, needed, mem_ctx); - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* write the request */ @@ -787,13 +841,13 @@ uint32 cli_spoolss_enumprinterdrivers ( switch (level) { case 1: - decode_printer_driver_1(r.buffer, r.returned, &ctr->info1); + decode_printer_driver_1(mem_ctx, r.buffer, r.returned, &ctr->info1); break; case 2: - decode_printer_driver_2(r.buffer, r.returned, &ctr->info2); + decode_printer_driver_2(mem_ctx, r.buffer, r.returned, &ctr->info2); break; case 3: - decode_printer_driver_3(r.buffer, r.returned, &ctr->info3); + decode_printer_driver_3(mem_ctx, r.buffer, r.returned, &ctr->info3); break; } } @@ -813,6 +867,7 @@ uint32 cli_spoolss_enumprinterdrivers ( */ uint32 cli_spoolss_getprinterdriverdir ( struct cli_state *cli, + TALLOC_CTX *mem_ctx, uint32 level, char* env, DRIVER_DIRECTORY_CTR *ctr @@ -835,10 +890,10 @@ uint32 cli_spoolss_getprinterdriverdir ( do { /* Initialise input parameters */ - init_buffer(&buffer, needed, cli->mem_ctx); + init_buffer(&buffer, needed, mem_ctx); - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* write the request */ @@ -864,7 +919,7 @@ uint32 cli_spoolss_getprinterdriverdir ( switch (level) { case 1: - decode_printerdriverdir_1(r.buffer, 1, &ctr->info1); + decode_printerdriverdir_1(mem_ctx, r.buffer, 1, &ctr->info1); break; } } @@ -883,6 +938,7 @@ uint32 cli_spoolss_getprinterdriverdir ( */ uint32 cli_spoolss_addprinterdriver ( struct cli_state *cli, + TALLOC_CTX *mem_ctx, uint32 level, PRINTER_DRIVER_CTR *ctr ) @@ -890,22 +946,22 @@ uint32 cli_spoolss_addprinterdriver ( prs_struct qbuf, rbuf; SPOOL_Q_ADDPRINTERDRIVER q; SPOOL_R_ADDPRINTERDRIVER r; - uint32 result; + uint32 result = NT_STATUS_UNSUCCESSFUL; fstring server; ZERO_STRUCT(q); ZERO_STRUCT(r); - + slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); strupper (server); /* Initialise input parameters */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* write the request */ - make_spoolss_q_addprinterdriver (&q, server, level, ctr); + make_spoolss_q_addprinterdriver (mem_ctx, &q, server, level, ctr); /* Marshall data and send request */ result = NT_STATUS_UNSUCCESSFUL; @@ -929,7 +985,7 @@ uint32 cli_spoolss_addprinterdriver ( done: prs_mem_free(&qbuf); prs_mem_free(&rbuf); - + return result; } @@ -938,6 +994,7 @@ done: */ uint32 cli_spoolss_addprinterex ( struct cli_state *cli, + TALLOC_CTX *mem_ctx, uint32 level, PRINTER_INFO_CTR *ctr ) @@ -961,12 +1018,12 @@ uint32 cli_spoolss_addprinterex ( /* Initialise input parameters */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* write the request */ - make_spoolss_q_addprinterex (&q, server, client, user, level, ctr); + make_spoolss_q_addprinterex (mem_ctx, &q, server, client, user, level, ctr); /* Marshall data and send request */ result = NT_STATUS_UNSUCCESSFUL; @@ -994,4 +1051,61 @@ done: return result; } +/********************************************************************** + * Delete a Printer Driver from the server (does not remove + * the driver files + */ +uint32 cli_spoolss_deleteprinterdriver ( + struct cli_state *cli, + TALLOC_CTX *mem_ctx, + char *arch, + char *driver +) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_DELETEPRINTERDRIVER q; + SPOOL_R_DELETEPRINTERDRIVER r; + uint32 result; + fstring server; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + + /* Initialise input parameters */ + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper (server); + + /* write the request */ + make_spoolss_q_deleteprinterdriver (mem_ctx, &q, server, arch, driver); + + /* Marshall data and send request */ + result = NT_STATUS_UNSUCCESSFUL; + if (!spoolss_io_q_deleteprinterdriver ("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli,SPOOLSS_DELETEPRINTERDRIVER , &qbuf, &rbuf)) + { + goto done; + } + + + /* Unmarshall response */ + result = NT_STATUS_UNSUCCESSFUL; + if (!spoolss_io_r_deleteprinterdriver ("", &r, &rbuf, 0)) + { + goto done; + } + + /* Return output parameters */ + result = r.status; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index 8a56a08b1d4..67eef52583f 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -104,8 +104,7 @@ BOOL cli_session_setup(struct cli_state *cli, /* * Plaintext mode needed, assume plaintext supplied. */ - fstrcpy(pword, pass); - unix_to_dos(pword,True); + passlen = clistr_push(cli, pword, pass, -1, STR_CONVERT|STR_TERMINATE); fstrcpy(ntpword, ""); ntpasslen = 0; } @@ -124,7 +123,7 @@ BOOL cli_session_setup(struct cli_state *cli, if (cli->protocol < PROTOCOL_NT1) { - set_message(cli->outbuf,10,1 + strlen(user) + passlen,True); + set_message(cli->outbuf,10, 0, True); CVAL(cli->outbuf,smb_com) = SMBsesssetupX; cli_setup_packet(cli); @@ -137,12 +136,20 @@ BOOL cli_session_setup(struct cli_state *cli, p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += passlen; - pstrcpy(p,user); - unix_to_dos(p,True); - strupper(p); + p += clistr_push(cli, p, user, -1, STR_CONVERT|STR_UPPER|STR_TERMINATE); + cli_setup_bcc(cli, p); } else { + uint32 capabilities; + + capabilities = CAP_NT_SMBS; + if (cli->use_level_II_oplocks) { + capabilities |= CAP_LEVEL_II_OPLOCKS; + } + if (cli->capabilities & CAP_UNICODE) { + capabilities |= CAP_UNICODE; + } set_message(cli->outbuf,13,0,True); CVAL(cli->outbuf,smb_com) = SMBsesssetupX; cli_setup_packet(cli); @@ -154,23 +161,17 @@ BOOL cli_session_setup(struct cli_state *cli, SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); SSVAL(cli->outbuf,smb_vwv7,passlen); SSVAL(cli->outbuf,smb_vwv8,ntpasslen); - SSVAL(cli->outbuf,smb_vwv11,CAP_NT_SMBS|(cli->use_level_II_oplocks ? CAP_LEVEL_II_OPLOCKS : 0)); + SIVAL(cli->outbuf,smb_vwv11,capabilities); p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += SVAL(cli->outbuf,smb_vwv7); memcpy(p,ntpword,ntpasslen); p += SVAL(cli->outbuf,smb_vwv8); - pstrcpy(p,user); - unix_to_dos(p,True); - strupper(p); - p = skip_string(p,1); - pstrcpy(p,workgroup); - unix_to_dos(p,True); - strupper(p); - p = skip_string(p,1); - pstrcpy(p,"Unix");p = skip_string(p,1); - pstrcpy(p,"Samba");p = skip_string(p,1); - set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False); + p += clistr_push(cli, p, user, -1, STR_CONVERT|STR_TERMINATE|STR_UPPER); + p += clistr_push(cli, p, workgroup, -1, STR_CONVERT|STR_TERMINATE|STR_UPPER); + p += clistr_push(cli, p, "Unix", -1, STR_CONVERT|STR_TERMINATE); + p += clistr_push(cli, p, "Samba", -1, STR_CONVERT|STR_TERMINATE); + cli_setup_bcc(cli, p); } cli_send_smb(cli); @@ -187,24 +188,17 @@ BOOL cli_session_setup(struct cli_state *cli, cli->vuid = SVAL(cli->inbuf,smb_uid); if (cli->protocol >= PROTOCOL_NT1) { - /* - * Save off some of the connected server - * info. - */ - char *server_domain,*server_os,*server_type; - server_os = smb_buf(cli->inbuf); - server_type = skip_string(server_os,1); - server_domain = skip_string(server_type,1); - fstrcpy(cli->server_os, server_os); - dos_to_unix(cli->server_os, True); - fstrcpy(cli->server_type, server_type); - dos_to_unix(cli->server_type, True); - fstrcpy(cli->server_domain, server_domain); - dos_to_unix(cli->server_domain, True); + /* + * Save off some of the connected server + * info. + */ + char *q = smb_buf(cli->inbuf); + q += clistr_pull(cli, cli->server_os, q, sizeof(fstring), -1, STR_TERMINATE|STR_CONVERT); + q += clistr_pull(cli, cli->server_type, q, sizeof(fstring), -1, STR_TERMINATE|STR_CONVERT); + q += clistr_pull(cli, cli->server_domain, q, sizeof(fstring), -1, STR_TERMINATE|STR_CONVERT); } fstrcpy(cli->user_name, user); - dos_to_unix(cli->user_name, True); return True; } @@ -257,12 +251,11 @@ BOOL cli_send_tconX(struct cli_state *cli, unix_to_dos(dos_pword,True); SMBencrypt((uchar *)dos_pword,(uchar *)cli->cryptkey,(uchar *)pword); } else { - if(!(cli->sec_mode & 2)) { + if((cli->sec_mode & 3) == 0) { /* * Non-encrypted passwords - convert to DOS codepage before using. */ - fstrcpy(pword,pass); - unix_to_dos(pword,True); + passlen = clistr_push(cli, pword, pass, -1, STR_CONVERT|STR_TERMINATE); } else { memcpy(pword, pass, passlen); } @@ -273,8 +266,7 @@ BOOL cli_send_tconX(struct cli_state *cli, unix_to_dos(fullshare, True); strupper(fullshare); - set_message(cli->outbuf,4, - 2 + strlen(fullshare) + passlen + strlen(dev),True); + set_message(cli->outbuf,4, 0, True); CVAL(cli->outbuf,smb_com) = SMBtconX; cli_setup_packet(cli); @@ -284,10 +276,10 @@ BOOL cli_send_tconX(struct cli_state *cli, p = smb_buf(cli->outbuf); memcpy(p,pword,passlen); p += passlen; - fstrcpy(p,fullshare); - p = skip_string(p,1); - pstrcpy(p,dev); - unix_to_dos(p,True); + p += clistr_push(cli, p, fullshare, -1, STR_CONVERT | STR_TERMINATE); + fstrcpy(p, dev); p += strlen(dev)+1; + + cli_setup_bcc(cli, p); SCVAL(cli->inbuf,smb_rcls, 1); @@ -302,7 +294,7 @@ BOOL cli_send_tconX(struct cli_state *cli, fstrcpy(cli->dev, "A:"); if (cli->protocol >= PROTOCOL_NT1) { - fstrcpy(cli->dev, smb_buf(cli->inbuf)); + clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE | STR_CONVERT); } if (strcasecmp(share,"IPC$")==0) { @@ -347,17 +339,11 @@ void cli_negprot_send(struct cli_state *cli) { char *p; int numprots; - int plength; memset(cli->outbuf,'\0',smb_size); /* setup the protocol strings */ - for (plength=0,numprots=0; - prots[numprots].name && prots[numprots].prot<=cli->protocol; - numprots++) - plength += strlen(prots[numprots].name)+2; - - set_message(cli->outbuf,0,plength,True); + set_message(cli->outbuf,0,0,True); p = smb_buf(cli->outbuf); for (numprots=0; @@ -370,6 +356,7 @@ void cli_negprot_send(struct cli_state *cli) } CVAL(cli->outbuf,smb_com) = SMBnegprot; + cli_setup_bcc(cli, p); cli_setup_packet(cli); CVAL(smb_buf(cli->outbuf),0) = 2; @@ -442,6 +429,12 @@ BOOL cli_negprot(struct cli_state *cli) cli->readbraw_supported = True; cli->writebraw_supported = True; } + /* work out if they sent us a workgroup */ + if (smb_buflen(cli->inbuf) > 8) { + clistr_pull(cli, cli->server_domain, + smb_buf(cli->inbuf)+8, sizeof(cli->server_domain), + smb_buflen(cli->inbuf)-8, STR_CONVERT|STR_UNICODE|STR_NOALIGN); + } } else if (cli->protocol >= PROTOCOL_LANMAN1) { cli->sec_mode = SVAL(cli->inbuf,smb_vwv1); cli->max_xmit = SVAL(cli->inbuf,smb_vwv2); @@ -461,6 +454,11 @@ BOOL cli_negprot(struct cli_state *cli) cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE); + /* a way to force ascii SMB */ + if (getenv("CLI_FORCE_ASCII")) { + cli->capabilities &= ~CAP_UNICODE; + } + return True; } @@ -560,7 +558,6 @@ retry: return(True); } - /**************************************************************************** open the client sockets ****************************************************************************/ @@ -582,8 +579,12 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) if (cli->port == 0) cli->port = 139; /* Set to default */ - cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, - cli->port, cli->timeout); + if (getenv("LIBSMB_PROG")) { + cli->fd = sock_exec(getenv("LIBSMB_PROG")); + } else { + cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, + cli->port, cli->timeout); + } if (cli->fd == -1) return False; @@ -677,7 +678,7 @@ BOOL cli_establish_connection(struct cli_state *cli, { DEBUG(1,("failed session request\n")); if (do_shutdown) - cli_shutdown(cli); + cli_shutdown(cli); return False; } diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index 19380498063..8d4a025fcc0 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -106,11 +106,23 @@ void cli_setup_packet(struct cli_state *cli) SSVAL(cli->outbuf,smb_uid,cli->vuid); SSVAL(cli->outbuf,smb_mid,cli->mid); if (cli->protocol > PROTOCOL_CORE) { + uint16 flags2; SCVAL(cli->outbuf,smb_flg,0x8); - SSVAL(cli->outbuf,smb_flg2,0x1); + flags2 = FLAGS2_LONG_PATH_COMPONENTS; + if (cli->capabilities & CAP_UNICODE) { + flags2 |= FLAGS2_UNICODE_STRINGS; + } + SSVAL(cli->outbuf,smb_flg2, flags2); } } +/**************************************************************************** +setup the bcc length of the packet from a pointer to the end of the data +****************************************************************************/ +void cli_setup_bcc(struct cli_state *cli, void *p) +{ + set_message_bcc(cli->outbuf, PTR_DIFF(p, smb_buf(cli->outbuf))); +} /**************************************************************************** diff --git a/source/libsmb/clierror.c b/source/libsmb/clierror.c index eb2ca624e85..6d499867905 100644 --- a/source/libsmb/clierror.c +++ b/source/libsmb/clierror.c @@ -198,11 +198,12 @@ int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num, uint32 *nt_rpc_ case ERRbadshare: return EBUSY; case ERRlock: return EBUSY; case ERROR_INVALID_NAME: return ENOENT; + case ERRnosuchshare: return ENODEV; } } if (rcls == ERRSRV) { switch (code) { - case ERRbadpw: return EACCES; + case ERRbadpw: return EPERM; case ERRaccess: return EACCES; case ERRnoresource: return ENOMEM; case ERRinvdevice: return ENODEV; diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c index 63706f7669e..56d2f63c799 100644 --- a/source/libsmb/clifile.c +++ b/source/libsmb/clifile.c @@ -33,7 +33,7 @@ BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst) memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True); + set_message(cli->outbuf,1, 0, True); CVAL(cli->outbuf,smb_com) = SMBmv; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -43,12 +43,13 @@ BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst) p = smb_buf(cli->outbuf); *p++ = 4; - pstrcpy(p,fname_src); - unix_to_dos(p,True); - p = skip_string(p,1); + p += clistr_push(cli, p, fname_src, -1, + STR_TERMINATE | STR_CONVERT); *p++ = 4; - pstrcpy(p,fname_dst); - unix_to_dos(p,True); + p += clistr_push(cli, p, fname_dst, -1, + STR_TERMINATE | STR_CONVERT); + + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { @@ -72,7 +73,7 @@ BOOL cli_unlink(struct cli_state *cli, char *fname) memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,1, 2 + strlen(fname),True); + set_message(cli->outbuf,1, 0,True); CVAL(cli->outbuf,smb_com) = SMBunlink; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -82,9 +83,9 @@ BOOL cli_unlink(struct cli_state *cli, char *fname) p = smb_buf(cli->outbuf); *p++ = 4; - pstrcpy(p,fname); - unix_to_dos(p,True); + p += clistr_push(cli, p, fname, -1, STR_TERMINATE | STR_CONVERT); + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; @@ -107,7 +108,7 @@ BOOL cli_mkdir(struct cli_state *cli, char *dname) memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,0, 2 + strlen(dname),True); + set_message(cli->outbuf,0, 0,True); CVAL(cli->outbuf,smb_com) = SMBmkdir; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -115,8 +116,9 @@ BOOL cli_mkdir(struct cli_state *cli, char *dname) p = smb_buf(cli->outbuf); *p++ = 4; - pstrcpy(p,dname); - unix_to_dos(p,True); + p += clistr_push(cli, p, dname, -1, STR_CONVERT|STR_TERMINATE); + + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { @@ -140,7 +142,7 @@ BOOL cli_rmdir(struct cli_state *cli, char *dname) memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,0, 2 + strlen(dname),True); + set_message(cli->outbuf,0, 0, True); CVAL(cli->outbuf,smb_com) = SMBrmdir; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -148,8 +150,9 @@ BOOL cli_rmdir(struct cli_state *cli, char *dname) p = smb_buf(cli->outbuf); *p++ = 4; - pstrcpy(p,dname); - unix_to_dos(p,True); + p += clistr_push(cli, p, dname, -1, STR_TERMINATE|STR_CONVERT); + + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { @@ -183,11 +186,11 @@ int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag) data = flag ? 1 : 0; if (!cli_send_trans(cli, SMBtrans2, - NULL, 0, /* name, length */ - -1, 0, /* fid, flags */ - &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ - &data, data_len, cli->max_xmit /* data, length, max */ + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, length, max */ + param, param_len, 2, /* param, length, max */ + &data, data_len, cli->max_xmit /* data, length, max */ )) { return False; } @@ -209,15 +212,17 @@ int cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag) Used in smbtorture. ****************************************************************************/ -int cli_nt_create_full(struct cli_state *cli, char *fname, uint32 DesiredAccess, uint32 FileAttributes, - uint32 ShareAccess, uint32 CreateDisposition, uint32 CreateOptions) +int cli_nt_create_full(struct cli_state *cli, char *fname, uint32 DesiredAccess, + uint32 FileAttributes, uint32 ShareAccess, + uint32 CreateDisposition, uint32 CreateOptions) { char *p; + int len; memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,24,1 + strlen(fname),True); + set_message(cli->outbuf,24,0,True); CVAL(cli->outbuf,smb_com) = SMBntcreateX; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -235,12 +240,17 @@ int cli_nt_create_full(struct cli_state *cli, char *fname, uint32 DesiredAccess, SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, CreateDisposition); SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, CreateOptions); SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02); - SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname)); p = smb_buf(cli->outbuf); - pstrcpy(p,fname); - unix_to_dos(p,True); - p = skip_string(p,1); + /* this alignment and termination is critical for netapp filers. Don't change */ + p += clistr_align_out(cli, p, STR_CONVERT); + len = clistr_push(cli, p, fname, -1, STR_CONVERT); + p += len; + SSVAL(cli->outbuf,smb_ntcreate_NameLength, len); + /* sigh. this copes with broken netapp filer behaviour */ + p += clistr_push(cli, p, "", -1, STR_TERMINATE); + + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { @@ -257,62 +267,13 @@ int cli_nt_create_full(struct cli_state *cli, char *fname, uint32 DesiredAccess, /**************************************************************************** open a file ****************************************************************************/ + int cli_nt_create(struct cli_state *cli, char *fname, uint32 DesiredAccess) { return cli_nt_create_full(cli, fname, DesiredAccess, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_EXISTS_OPEN, 0x0); } -/**************************************************************************** -open a file -****************************************************************************/ -int cli_nt_create_uni(struct cli_state *cli, char *fname, uint32 DesiredAccess) -{ - pstring uni; - char *p; - - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); - - set_message(cli->outbuf,24,(strlen(fname) + 1) * 2 + 1,True); - - CVAL(cli->outbuf,smb_com) = SMBntcreateX; - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); - - SSVAL(cli->outbuf,smb_vwv0,0xFF); - if (cli->use_oplocks) - SIVAL(cli->outbuf,smb_ntcreate_Flags, REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); - else - SIVAL(cli->outbuf,smb_ntcreate_Flags, 0); - SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0); - SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, DesiredAccess); - SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0); - SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03); - SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01); - SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0); - SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02); - SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname) * 2); - - p = smb_buf(cli->outbuf); - p++; /* Alignment */ - pstrcpy(uni, fname); - unix_to_dos(uni, True); - dos_struni2(p, uni, (strlen(fname) + 1) * 2); - - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { - return -1; - } - - if (CVAL(cli->inbuf,smb_rcls) != 0) { - return -1; - } - - return SVAL(cli->inbuf,smb_vwv2 + 1); -} - - /**************************************************************************** open a file WARNING: if you open with O_WRONLY then getattrE won't work! @@ -353,7 +314,7 @@ int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode) memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,15,1 + strlen(fname),True); + set_message(cli->outbuf,15,0,True); CVAL(cli->outbuf,smb_com) = SMBopenX; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -375,9 +336,9 @@ int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode) } p = smb_buf(cli->outbuf); - pstrcpy(p,fname); - unix_to_dos(p,True); - p = skip_string(p,1); + p += clistr_push(cli, p, fname, -1, STR_TERMINATE | STR_CONVERT); + + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { @@ -436,7 +397,7 @@ BOOL cli_lock(struct cli_state *cli, int fnum, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0', smb_size); - set_message(cli->outbuf,8,10,True); + set_message(cli->outbuf,8,0,True); CVAL(cli->outbuf,smb_com) = SMBlockingX; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -453,6 +414,11 @@ BOOL cli_lock(struct cli_state *cli, int fnum, SSVAL(p, 0, cli->pid); SIVAL(p, 2, offset); SIVAL(p, 6, len); + + p += 10; + + cli_setup_bcc(cli, p); + cli_send_smb(cli); cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000); @@ -481,7 +447,7 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len) memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,8,10,True); + set_message(cli->outbuf,8,0,True); CVAL(cli->outbuf,smb_com) = SMBlockingX; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -498,7 +464,8 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len) SSVAL(p, 0, cli->pid); SIVAL(p, 2, offset); SIVAL(p, 6, len); - + p += 10; + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; @@ -528,7 +495,7 @@ BOOL cli_lock64(struct cli_state *cli, int fnum, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0', smb_size); - set_message(cli->outbuf,8,20,True); + set_message(cli->outbuf,8,0,True); CVAL(cli->outbuf,smb_com) = SMBlockingX; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -543,8 +510,11 @@ BOOL cli_lock64(struct cli_state *cli, int fnum, p = smb_buf(cli->outbuf); SIVAL(p, 0, cli->pid); - SOFF_T_R(p, 0, offset); + SOFF_T_R(p, 4, offset); SOFF_T_R(p, 12, len); + p += 20; + + cli_setup_bcc(cli, p); cli_send_smb(cli); cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000); @@ -573,7 +543,7 @@ BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_ memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,8,20,True); + set_message(cli->outbuf,8,0,True); CVAL(cli->outbuf,smb_com) = SMBlockingX; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -590,7 +560,8 @@ BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_ SIVAL(p, 0, cli->pid); SOFF_T_R(p, 4, offset); SOFF_T_R(p, 12, len); - + p += 20; + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { return False; @@ -669,16 +640,17 @@ BOOL cli_getatr(struct cli_state *cli, char *fname, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,0,strlen(fname)+2,True); + set_message(cli->outbuf,0,0,True); CVAL(cli->outbuf,smb_com) = SMBgetatr; SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); p = smb_buf(cli->outbuf); - *p = 4; - pstrcpy(p+1, fname); - unix_to_dos(p+1,True); + *p++ = 4; + p += clistr_push(cli, p, fname, -1, STR_TERMINATE | STR_CONVERT); + + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { @@ -716,7 +688,7 @@ BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t) memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,8,strlen(fname)+4,True); + set_message(cli->outbuf,8,0,True); CVAL(cli->outbuf,smb_com) = SMBsetatr; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -726,11 +698,11 @@ BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t) put_dos_date3(cli->outbuf,smb_vwv1, t); p = smb_buf(cli->outbuf); - *p = 4; - pstrcpy(p+1, fname); - unix_to_dos(p+1,True); - p = skip_string(p,1); - *p = 4; + *p++ = 4; + p += clistr_push(cli, p, fname, -1, STR_TERMINATE | STR_CONVERT); + *p++ = 4; + + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { @@ -758,14 +730,15 @@ BOOL cli_chkpath(struct cli_state *cli, char *path) if (!*path2) *path2 = '\\'; memset(cli->outbuf,'\0',smb_size); - set_message(cli->outbuf,0,4 + strlen(path2),True); + set_message(cli->outbuf,0,0,True); SCVAL(cli->outbuf,smb_com,SMBchkpth); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); p = smb_buf(cli->outbuf); *p++ = 4; - safe_strcpy(p,path2,strlen(path2)); - unix_to_dos(p,True); + p += clistr_push(cli, p, path2, -1, STR_TERMINATE | STR_CONVERT); + + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { @@ -802,3 +775,44 @@ BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail) return True; } + +/**************************************************************************** +create and open a temporary file +****************************************************************************/ +int cli_ctemp(struct cli_state *cli, char *path, char **tmp_path) +{ + char *p; + + memset(cli->outbuf,'\0',smb_size); + memset(cli->inbuf,'\0',smb_size); + + set_message(cli->outbuf,1,strlen(path)+2,True); + + CVAL(cli->outbuf,smb_com) = SMBctemp; + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_packet(cli); + + SSVAL(cli->outbuf,smb_vwv0,0); + + p = smb_buf(cli->outbuf); + *p++ = 4; + p += clistr_push(cli, p, path, -1, STR_TERMINATE | STR_CONVERT); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { + return -1; + } + + if (CVAL(cli->inbuf,smb_rcls) != 0) { + return -1; + } + + if (tmp_path) { + pstring path2; + clistr_pull(cli, path2, smb_buf(cli->inbuf)+1, + sizeof(path2), -1, STR_TERMINATE | STR_CONVERT); + *tmp_path = strdup(path2); + } + + return SVAL(cli->inbuf,smb_vwv0); +} diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c index 2e904e06b7d..a04c691fa49 100644 --- a/source/libsmb/clilist.c +++ b/source/libsmb/clilist.c @@ -30,7 +30,8 @@ The length of the structure is returned The structure of a long filename depends on the info level. 260 is used by NT and 2 is used by OS/2 ****************************************************************************/ -static int interpret_long_filename(int level,char *p,file_info *finfo) +static int interpret_long_filename(struct cli_state *cli, + int level,char *p,file_info *finfo) { extern file_info def_finfo; @@ -47,8 +48,10 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) finfo->mtime = make_unix_date2(p+12); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); - pstrcpy(finfo->name,p+27); - dos_to_unix(finfo->name,True); + clistr_pull(cli, finfo->name, p+27, + sizeof(finfo->name), + -1, + STR_TERMINATE | STR_CONVERT); } return(28 + CVAL(p,26)); @@ -60,8 +63,10 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) finfo->mtime = make_unix_date2(p+12); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); - pstrcpy(finfo->name,p+31); - dos_to_unix(finfo->name,True); + clistr_pull(cli, finfo->name, p+31, + sizeof(finfo->name), + -1, + STR_TERMINATE | STR_CONVERT); } return(32 + CVAL(p,30)); @@ -74,8 +79,10 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) finfo->mtime = make_unix_date2(p+16); finfo->size = IVAL(p,20); finfo->mode = CVAL(p,28); - pstrcpy(finfo->name,p+33); - dos_to_unix(finfo->name,True); + clistr_pull(cli, finfo->name, p+33, + sizeof(finfo->name), + -1, + STR_TERMINATE | STR_CONVERT); } return(SVAL(p,4)+4); @@ -87,15 +94,17 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) finfo->mtime = make_unix_date2(p+16); finfo->size = IVAL(p,20); finfo->mode = CVAL(p,28); - pstrcpy(finfo->name,p+37); - dos_to_unix(finfo->name,True); + clistr_pull(cli, finfo->name, p+37, + sizeof(finfo->name), + -1, + STR_TERMINATE | STR_CONVERT); } return(SVAL(p,4)+4); case 260: /* NT uses this, but also accepts 2 */ if (finfo) { int ret = SVAL(p,0); - int namelen, slen; + int namelen; p += 4; /* next entry offset */ p += 4; /* fileindex */ @@ -122,18 +131,21 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) finfo->mode = CVAL(p,0); p += 4; namelen = IVAL(p,0); p += 4; p += 4; /* EA size */ - slen = SVAL(p, 0); + /* slen = SVAL(p, 0); */ p += 2; - if (p[1] == 0 && slen > 1) { - /* NT has stuffed up again */ - unistr_to_dos(finfo->short_name, p, slen/2); - } else { - strncpy(finfo->short_name, p, 12); - finfo->short_name[12] = 0; + { + /* stupid NT bugs. grr */ + int flags = STR_CONVERT; + if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE; + clistr_pull(cli, finfo->short_name, p, + sizeof(finfo->short_name), + 24, flags); } p += 24; /* short name? */ - StrnCpy(finfo->name,p,MIN(sizeof(finfo->name)-1,namelen)); - dos_to_unix(finfo->name,True); + clistr_pull(cli, finfo->name, p, + sizeof(finfo->name), + namelen, + STR_CONVERT); return(ret); } return(SVAL(p,0)); @@ -147,12 +159,11 @@ static int interpret_long_filename(int level,char *p,file_info *finfo) /**************************************************************************** do a directory listing, calling fn on each file found ****************************************************************************/ -int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, - void (*fn)(file_info *, const char *)) +int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, + void (*fn)(file_info *, const char *, void *), void *state) { int max_matches = 512; - /* NT uses 260, OS/2 uses 2. Both accept 1. */ - int info_level = cli->protocolcapabilities&CAP_NT_SMBS)?260:1; + pstrcpy(mask,Mask); - unix_to_dos(mask,True); while (ff_eos == 0) { loop_count++; @@ -181,8 +194,6 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, break; } - param_len = 12+strlen(mask)+1; - if (First) { setup = TRANSACT2_FINDFIRST; SSVAL(param,0,attribute); /* attribute */ @@ -190,7 +201,9 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, SSVAL(param,4,4+2); /* resume required + close on end */ SSVAL(param,6,info_level); SIVAL(param,8,0); - pstrcpy(param+12,mask); + p = param+12; + p += clistr_push(cli, param+12, mask, -1, + STR_TERMINATE | STR_CONVERT); } else { setup = TRANSACT2_FINDNEXT; SSVAL(param,0,ff_dir_handle); @@ -198,14 +211,15 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, SSVAL(param,4,info_level); SIVAL(param,6,0); /* ff_resume_key */ SSVAL(param,10,8+4+2); /* continue + resume required + close on end */ - pstrcpy(param+12,mask); - - DEBUG(5,("hand=0x%X ff_lastname=%d mask=%s\n", - ff_dir_handle,ff_lastname,mask)); + p = param+12; + p += clistr_push(cli, param+12, mask, -1, + STR_TERMINATE | STR_CONVERT); } + param_len = PTR_DIFF(p, param); + if (!cli_send_trans(cli, SMBtrans2, - NULL, 0, /* Name, length */ + NULL, /* Name */ -1, 0, /* fid, flags */ &setup, 1, 0, /* setup, length, max */ param, param_len, 10, /* param, length, max */ @@ -254,19 +268,24 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, switch(info_level) { case 260: - StrnCpy(mask,p+ff_lastname, - MIN(sizeof(mask)-1,data_len-ff_lastname)); + clistr_pull(cli, mask, p+ff_lastname, + sizeof(mask), + data_len-ff_lastname, + STR_TERMINATE | + STR_CONVERT); break; case 1: - pstrcpy(mask,p + ff_lastname + 1); + clistr_pull(cli, mask, p+ff_lastname+1, + sizeof(mask), + -1, + STR_TERMINATE | + STR_CONVERT); break; } } else { pstrcpy(mask,""); } - dos_to_unix(mask, True); - /* and add them to the dirlist pool */ dirlist = Realloc(dirlist,dirlist_len + data_len); @@ -278,7 +297,7 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, /* put in a length for the last entry, to ensure we can chain entries into the next packet */ for (p2=p,i=0;i<(ff_searchcount-1);i++) - p2 += interpret_long_filename(info_level,p2,NULL); + p2 += interpret_long_filename(cli,info_level,p2,NULL); SSVAL(p2,0,data_len - PTR_DIFF(p2,p)); /* grab the data for later use */ @@ -299,8 +318,8 @@ int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, } for (p=dirlist,i=0;ictime = make_unix_date(p+22); finfo->mtime = finfo->atime = finfo->ctime; finfo->size = IVAL(p,26); - pstrcpy(finfo->name,p+30); + clistr_pull(cli, finfo->name, p+30, sizeof(finfo->name), 12, STR_CONVERT|STR_ASCII); if (strcmp(finfo->name, "..") && strcmp(finfo->name, ".")) fstrcpy(finfo->short_name,finfo->name); @@ -340,7 +359,7 @@ static int interpret_short_filename(char *p,file_info *finfo) but should otherwise not be used ****************************************************************************/ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, - void (*fn)(file_info *, const char *)) + void (*fn)(file_info *, const char *, void *), void *state) { char *p; int received = 0; @@ -360,12 +379,9 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - if (first) - set_message(cli->outbuf,2,5 + strlen(mask),True); - else - set_message(cli->outbuf,2,5 + 21,True); + set_message(cli->outbuf,2,0,True); - CVAL(cli->outbuf,smb_com) = SMBffirst; + CVAL(cli->outbuf,smb_com) = SMBsearch; SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); @@ -376,21 +392,19 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, p = smb_buf(cli->outbuf); *p++ = 4; - if (first) - pstrcpy(p,mask); - else - pstrcpy(p,""); - p += strlen(p) + 1; - + p += clistr_push(cli, p, first?mask:"", -1, STR_TERMINATE|STR_CONVERT); *p++ = 5; if (first) { SSVAL(p,0,0); + p += 2; } else { SSVAL(p,0,21); p += 2; memcpy(p,status,21); + p += 21; } + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) break; @@ -420,7 +434,7 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,2,5 + 21,True); + set_message(cli->outbuf,2,0,True); CVAL(cli->outbuf,smb_com) = SMBfclose; SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); @@ -436,7 +450,9 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, SSVAL(p, 0, 21); p += 2; memcpy(p,status,21); + p += 21; + cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) { DEBUG(0,("Error closing search: %s\n",smb_errstr(cli->inbuf))); @@ -445,10 +461,24 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, for (p=dirlist,i=0;iprotocol <= PROTOCOL_LANMAN1) { + return cli_list_old(cli, Mask, attribute, fn, state); + } + return cli_list_new(cli, Mask, attribute, fn, state); +} diff --git a/source/libsmb/climessage.c b/source/libsmb/climessage.c index c15fdbce8c5..87f81754599 100644 --- a/source/libsmb/climessage.c +++ b/source/libsmb/climessage.c @@ -41,15 +41,13 @@ BOOL cli_message_start(struct cli_state *cli, char *host, char *username, p = smb_buf(cli->outbuf); *p++ = 4; - pstrcpy(p,username); - unix_to_dos(p,True); - p = skip_string(p,1); + p += clistr_push(cli, p, username, -1, + STR_TERMINATE|STR_CONVERT); *p++ = 4; - pstrcpy(p,host); - unix_to_dos(p,True); - p = skip_string(p,1); + p += clistr_push(cli, p, host, -1, + STR_TERMINATE|STR_CONVERT); - set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False); + cli_setup_bcc(cli, p); cli_send_smb(cli); diff --git a/source/libsmb/clirap.c b/source/libsmb/clirap.c index 085b1c35bb9..5050caf0732 100644 --- a/source/libsmb/clirap.c +++ b/source/libsmb/clirap.c @@ -27,18 +27,15 @@ /**************************************************************************** Call a remote api on an arbitrary pipe. takes param, data and setup buffers. ****************************************************************************/ -BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len, +BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, uint16 *setup, uint32 setup_count, uint32 max_setup_count, char *params, uint32 param_count, uint32 max_param_count, char *data, uint32 data_count, uint32 max_data_count, char **rparam, uint32 *rparam_count, char **rdata, uint32 *rdata_count) { - if (pipe_name_len == 0) - pipe_name_len = strlen(pipe_name); - cli_send_trans(cli, SMBtrans, - pipe_name, pipe_name_len, + pipe_name, 0,0, /* fid, flags */ setup, setup_count, max_setup_count, params, param_count, max_param_count, @@ -59,8 +56,8 @@ BOOL cli_api(struct cli_state *cli, char **rdata, int *rdrcnt) { cli_send_trans(cli,SMBtrans, - PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */ - 0,0, /* fid, flags */ + PIPE_LANMAN, /* Name */ + 0,0, /* fid, flags */ NULL,0,0, /* Setup, length, max */ param, prcnt, mprcnt, /* Params, length, max */ data, drcnt, mdrcnt /* Data, length, max */ @@ -137,7 +134,7 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation) /**************************************************************************** call a NetShareEnum - try and browse available connections on a host ****************************************************************************/ -int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *)) +int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state) { char *rparam = NULL; char *rdata = NULL; @@ -182,9 +179,12 @@ int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, co int type = SVAL(p,14); int comment_offset = IVAL(p,16) & 0xFFFF; char *cmnt = comment_offset?(rdata+comment_offset-converter):""; - dos_to_unix(sname,True); - dos_to_unix(cmnt,True); - fn(sname, type, cmnt); + pstring s1, s2; + + pstrcpy(s1, dos_to_unix(sname, False)); + pstrcpy(s2, dos_to_unix(cmnt, False)); + + fn(s1, type, s2, state); } } else { DEBUG(4,("NetShareEnum res=%d\n", res)); @@ -210,7 +210,8 @@ The callback function takes 3 arguments: the machine name, the server type and the comment. ****************************************************************************/ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, - void (*fn)(const char *, uint32, const char *)) + void (*fn)(const char *, uint32, const char *, void *), + void *state) { char *rparam = NULL; char *rdata = NULL; @@ -219,7 +220,7 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, pstring param; int uLevel = 1; int count = -1; - + /* send a SMBtrans command with api NetServerEnum */ p = param; SSVAL(p,0,0x68); /* api number */ @@ -228,17 +229,16 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, p = skip_string(p,1); pstrcpy(p,"B16BBDz"); - + p = skip_string(p,1); SSVAL(p,0,uLevel); SSVAL(p,2,CLI_BUFFER_SIZE); p += 4; SIVAL(p,0,stype); p += 4; - - pstrcpy(p, workgroup); - unix_to_dos(p, True); - p = skip_string(p,1); + + p += clistr_push(cli, p, workgroup, -1, + STR_TERMINATE | STR_CONVERT | STR_ASCII); if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */ @@ -259,13 +259,15 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, char *sname = p; int comment_offset = (IVAL(p,22) & 0xFFFF)-converter; char *cmnt = comment_offset?(rdata+comment_offset):""; + pstring s1, s2; + if (comment_offset < 0 || comment_offset > rdrcnt) continue; stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY; - dos_to_unix(sname, True); - dos_to_unix(cmnt, True); - fn(sname, stype, cmnt); + pstrcpy(s1, dos_to_unix(sname, False)); + pstrcpy(s2, dos_to_unix(cmnt, False)); + fn(s1, stype, s2, state); } } } @@ -349,7 +351,7 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char data_len = 532; if (cli_send_trans(cli,SMBtrans, - PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */ + PIPE_LANMAN, /* name */ 0,0, /* fid, flags */ NULL,0,0, /* setup, length, max */ param,param_len,2, /* param, length, max */ @@ -391,17 +393,19 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, int count=8; BOOL ret; time_t (*date_fn)(void *); + char *p; - param_len = strlen(fname) + 7; + p = param; + memset(p, 0, 6); + SSVAL(p, 0, SMB_INFO_STANDARD); + p += 6; + p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE | STR_CONVERT); - memset(param, 0, param_len); - SSVAL(param, 0, SMB_INFO_STANDARD); - pstrcpy(¶m[6], fname); - unix_to_dos(¶m[6],True); + param_len = PTR_DIFF(p, param); do { ret = (cli_send_trans(cli, SMBtrans2, - NULL, 0, /* Name, length */ + NULL, /* Name */ -1, 0, /* fid, flags */ &setup, 1, 0, /* setup, length, max */ param, param_len, 10, /* param, length, max */ @@ -465,16 +469,18 @@ BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, uint16 setup = TRANSACT2_QPATHINFO; pstring param; char *rparam=NULL, *rdata=NULL; + char *p; - param_len = strlen(fname) + 7; + p = param; + memset(p, 0, 6); + SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO); + p += 6; + p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE | STR_CONVERT); - memset(param, 0, param_len); - SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO); - pstrcpy(¶m[6], fname); - unix_to_dos(¶m[6],True); + param_len = PTR_DIFF(p, param); if (!cli_send_trans(cli, SMBtrans2, - NULL, 0, /* name, length */ + NULL, /* name */ -1, 0, /* fid, flags */ &setup, 1, 0, /* setup, length, max */ param, param_len, 10, /* param, length, max */ @@ -546,7 +552,7 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum, SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO); if (!cli_send_trans(cli, SMBtrans2, - NULL, 0, /* name, length */ + NULL, /* name */ -1, 0, /* fid, flags */ &setup, 1, 0, /* setup, length, max */ param, param_len, 2, /* param, length, max */ @@ -592,3 +598,46 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum, return True; } +/**************************************************************************** +send a qfileinfo call +****************************************************************************/ +BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char *outdata) +{ + int data_len = 0; + int param_len = 0; + uint16 setup = TRANSACT2_QFILEINFO; + pstring param; + char *rparam=NULL, *rdata=NULL; + + /* if its a win95 server then fail this - win95 totally screws it + up */ + if (cli->win95) return False; + + param_len = 4; + + memset(param, 0, param_len); + SSVAL(param, 0, fnum); + SSVAL(param, 2, level); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, length, max */ + param, param_len, 2, /* param, length, max */ + NULL, data_len, cli->max_xmit /* data, length, max */ + )) { + return False; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, ¶m_len, + &rdata, &data_len)) { + return False; + } + + memcpy(outdata, rdata, data_len); + + if (rdata) free(rdata); + if (rparam) free(rparam); + return True; +} diff --git a/source/libsmb/clireadwrite.c b/source/libsmb/clireadwrite.c index 86a51da8352..458532cb2ed 100644 --- a/source/libsmb/clireadwrite.c +++ b/source/libsmb/clireadwrite.c @@ -26,7 +26,8 @@ /**************************************************************************** issue a single SMBread and don't wait for a reply ****************************************************************************/ -static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset, + +static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset, size_t size, int i) { memset(cli->outbuf,'\0',smb_size); @@ -45,92 +46,88 @@ static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset, SSVAL(cli->outbuf,smb_vwv6,size); SSVAL(cli->outbuf,smb_mid,cli->mid + i); - cli_send_smb(cli); + return cli_send_smb(cli); } /**************************************************************************** - read from a file + Read size bytes at offset offset using SMBreadX. ****************************************************************************/ -size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) + +ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) { + uint32 ecode; + uint8 eclass; char *p; - int total = -1; - int issued=0; - int received=0; -/* - * There is a problem in this code when mpx is more than one. - * for some reason files can get corrupted when being read. - * Until we understand this fully I am serializing reads (one - * read/one reply) for now. JRA. - */ -#if 0 - int mpx = MAX(cli->max_mux-1, 1); -#else - int mpx = 1; -#endif - int block = (cli->max_xmit - (smb_size+32)) & ~1023; - int mid; - int blocks = (size + (block-1)) / block; + int size2; + int readsize; + ssize_t total = 0; - if (size == 0) return 0; + if (size == 0) + return 0; - while (received < blocks) { - int size2; + /* + * Set readsize to the maximum size we can handle in one readX, + * rounded down to a multiple of 1024. + */ - while (issued - received < mpx && issued < blocks) { - int size1 = MIN(block, size-issued*block); - cli_issue_read(cli, fnum, offset+issued*block, size1, issued); - issued++; - } + readsize = (cli->max_xmit - (smb_size+32)) & ~1023; - if (!cli_receive_smb(cli)) { - return total; - } + while (total < size) { + readsize = MIN(readsize, size-total); - received++; - mid = SVAL(cli->inbuf, smb_mid) - cli->mid; - size2 = SVAL(cli->inbuf, smb_vwv5); + /* Issue a read and receive a reply */ - if (CVAL(cli->inbuf,smb_rcls) != 0) { - blocks = MIN(blocks, mid-1); - continue; - } + if (!cli_issue_read(cli, fnum, offset, readsize, 0)) + return -1; - if (size2 <= 0) { - blocks = MIN(blocks, mid-1); - /* this distinguishes EOF from an error */ - total = MAX(total, 0); - continue; - } + if (!cli_receive_smb(cli)) + return -1; + + /* + * Check for error. Because the client library doesn't support + * STATUS32, we need to check for and ignore the more data error + * for pipe support. + */ - if (size2 > block) { - DEBUG(0,("server returned more than we wanted!\n")); + if (cli_error(cli, &eclass, &ecode, NULL) && + (eclass != ERRDOS && ecode != ERRmoredata)) { return -1; } - if (mid >= issued) { - DEBUG(0,("invalid mid from server!\n")); + + size2 = SVAL(cli->inbuf, smb_vwv5); + + if (size2 > readsize) { + DEBUG(5,("server returned more than we wanted!\n")); + return -1; + } else if (size2 < 0) { + DEBUG(5,("read return < 0!\n")); return -1; } + + /* Copy data into buffer */ + p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); + memcpy(buf + total, p, size2); - memcpy(buf+mid*block, p, size2); + total += size2; + offset += size2; - total = MAX(total, mid*block + size2); - } + /* + * If the server returned less than we asked for we're at EOF. + */ - while (received < issued) { - cli_receive_smb(cli); - received++; + if (size2 < readsize) + break; } - + return total; } - /**************************************************************************** issue a single SMBwrite and don't wait for a reply ****************************************************************************/ -static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf, + +static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf, size_t size, int i) { char *p; @@ -138,7 +135,10 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,12,size,True); + if (size > 0xFFFF) + set_message(cli->outbuf,14,0,True); + else + set_message(cli->outbuf,12,0,True); CVAL(cli->outbuf,smb_com) = SMBwriteX; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -152,17 +152,19 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 SSVAL(cli->outbuf,smb_vwv7,mode); SSVAL(cli->outbuf,smb_vwv8,(mode & 0x0008) ? size : 0); + SSVAL(cli->outbuf,smb_vwv9,((size>>16)&1)); SSVAL(cli->outbuf,smb_vwv10,size); SSVAL(cli->outbuf,smb_vwv11, smb_buf(cli->outbuf) - smb_base(cli->outbuf)); p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11); memcpy(p, buf, size); + cli_setup_bcc(cli, p+size); SSVAL(cli->outbuf,smb_mid,cli->mid + i); show_msg(cli->outbuf); - cli_send_smb(cli); + return cli_send_smb(cli); } /**************************************************************************** @@ -172,6 +174,7 @@ static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint1 0x0004 use raw named pipe protocol 0x0008 start of message mode named pipe protocol ****************************************************************************/ + ssize_t cli_write(struct cli_state *cli, int fnum, uint16 write_mode, char *buf, off_t offset, size_t size) @@ -185,45 +188,39 @@ ssize_t cli_write(struct cli_state *cli, while (received < blocks) { - while ((issued - received < mpx) && (issued < blocks)) - { + while ((issued - received < mpx) && (issued < blocks)) { int bsent = issued * block; int size1 = MIN(block, size - bsent); - cli_issue_write(cli, fnum, offset + bsent, + if (!cli_issue_write(cli, fnum, offset + bsent, write_mode, buf + bsent, - size1, issued); + size1, issued)) + return -1; issued++; } if (!cli_receive_smb(cli)) - { return bwritten; - } received++; if (CVAL(cli->inbuf,smb_rcls) != 0) - { break; - } bwritten += SVAL(cli->inbuf, smb_vwv2); } while (received < issued && cli_receive_smb(cli)) - { received++; - } return bwritten; } - /**************************************************************************** write to a file using a SMBwrite and not bypassing 0 byte writes ****************************************************************************/ + ssize_t cli_smbwrite(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size1) { @@ -236,7 +233,7 @@ ssize_t cli_smbwrite(struct cli_state *cli, memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); - set_message(cli->outbuf,5, 3 + size,True); + set_message(cli->outbuf,5, 0,True); CVAL(cli->outbuf,smb_com) = SMBwrite; SSVAL(cli->outbuf,smb_tid,cli->cnum); @@ -249,20 +246,23 @@ ssize_t cli_smbwrite(struct cli_state *cli, p = smb_buf(cli->outbuf); *p++ = 1; - SSVAL(p, 0, size); - memcpy(p+2, buf, size); + SSVAL(p, 0, size); p += 2; + memcpy(p, buf, size); p += size; + + cli_setup_bcc(cli, p); - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { + if (!cli_send_smb(cli)) + return -1; + + if (!cli_receive_smb(cli)) return -1; - } - if (CVAL(cli->inbuf,smb_rcls) != 0) { + if (CVAL(cli->inbuf,smb_rcls) != 0) return -1; - } size = SVAL(cli->inbuf,smb_vwv0); - if (size == 0) break; + if (size == 0) + break; size1 -= size; total += size; @@ -270,4 +270,3 @@ ssize_t cli_smbwrite(struct cli_state *cli, return total; } - diff --git a/source/libsmb/clisecdesc.c b/source/libsmb/clisecdesc.c index 0b52d625131..69c7d5f73fd 100644 --- a/source/libsmb/clisecdesc.c +++ b/source/libsmb/clisecdesc.c @@ -28,12 +28,11 @@ /**************************************************************************** query the security descriptor for a open file ****************************************************************************/ -SEC_DESC *cli_query_secdesc(struct cli_state *cli,int fd) +SEC_DESC *cli_query_secdesc(struct cli_state *cli,int fd, TALLOC_CTX *mem_ctx) { char param[8]; char *rparam=NULL, *rdata=NULL; int rparam_count=0, rdata_count=0; - TALLOC_CTX *mem_ctx; prs_struct pd; SEC_DESC *psd = NULL; @@ -58,11 +57,6 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli,int fd) goto cleanup; } - if ((mem_ctx = talloc_init()) == NULL) { - DEBUG(0,("talloc_init failed.\n")); - goto cleanup; - } - prs_init(&pd, rdata_count, mem_ctx, UNMARSHALL); prs_append_data(&pd, rdata, rdata_count); pd.data_offset = 0; @@ -74,7 +68,6 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli,int fd) cleanup: - talloc_destroy(mem_ctx); safe_free(rparam); safe_free(rdata); @@ -82,9 +75,6 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli,int fd) return psd; } - - - /**************************************************************************** set the security descriptor for a open file ****************************************************************************/ @@ -143,4 +133,3 @@ BOOL cli_set_secdesc(struct cli_state *cli,int fd, SEC_DESC *sd) prs_mem_free(&pd); return ret; } - diff --git a/source/libsmb/clitrans.c b/source/libsmb/clitrans.c index 5cd6ae30ce0..d21d179126a 100644 --- a/source/libsmb/clitrans.c +++ b/source/libsmb/clitrans.c @@ -28,7 +28,7 @@ send a SMB trans or trans2 request ****************************************************************************/ BOOL cli_send_trans(struct cli_state *cli, int trans, - char *name, int pipe_name_len, + char *pipe_name, int fid, int flags, uint16 *setup, int lsetup, int msetup, char *param, int lparam, int mparam, @@ -39,6 +39,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, int tot_data=0,tot_param=0; char *outdata,*outparam; char *p; + int pipe_name_len=0; this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */ this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam)); @@ -49,7 +50,11 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, SSVAL(cli->outbuf,smb_tid, cli->cnum); cli_setup_packet(cli); - outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len+1 : 3); + if (pipe_name) { + pipe_name_len = clistr_push(cli, smb_buf(cli->outbuf), pipe_name, -1, STR_TERMINATE); + } + + outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len : 3); outdata = outparam+this_lparam; /* primary request */ @@ -68,9 +73,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, for (i=0;ioutbuf,smb_setup+i*2,setup[i]); p = smb_buf(cli->outbuf); - if (trans==SMBtrans) { - memcpy(p,name, pipe_name_len + 1); /* name[] */ - } else { + if (trans != SMBtrans) { *p++ = 0; /* put in a null smb_name */ *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */ } @@ -78,8 +81,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, memcpy(outparam,param,this_lparam); if (this_ldata) /* data[] */ memcpy(outdata,data,this_ldata); - set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */ - PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); + cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); cli_send_smb(cli); @@ -119,8 +121,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, memcpy(outparam,param+tot_param,this_lparam); if (this_ldata) /* data[] */ memcpy(outdata,data+tot_data,this_ldata); - set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */ - PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); + cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); cli_send_smb(cli); @@ -288,8 +289,7 @@ BOOL cli_send_nt_trans(struct cli_state *cli, if (this_ldata) /* data[] */ memcpy(outdata,data,this_ldata); - set_message(cli->outbuf,19+lsetup, /* wcnt, bcc */ - PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); + cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); cli_send_smb(cli); @@ -328,8 +328,7 @@ BOOL cli_send_nt_trans(struct cli_state *cli, memcpy(outparam,param+tot_param,this_lparam); if (this_ldata) /* data[] */ memcpy(outdata,data+tot_data,this_ldata); - set_message(cli->outbuf,18, - PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); + cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); cli_send_smb(cli); diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c index 816804753e7..465198dfad4 100644 --- a/source/libsmb/namequery.c +++ b/source/libsmb/namequery.c @@ -190,6 +190,96 @@ BOOL name_status_find(int type, struct in_addr to_ip, char *name) return True; } +/**************************************************************************** + Do a NetBIOS name registation to try to claim a name ... +***************************************************************************/ +BOOL name_register(int fd, const char *name, int name_type, + struct in_addr name_ip, int opcode, + BOOL bcast, + struct in_addr to_ip, int *count) +{ + int retries = 3; + struct timeval tval; + struct packet_struct p; + struct packet_struct *p2; + struct nmb_packet *nmb = &p.packet.nmb; + struct in_addr register_ip; + + DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip))); + + register_ip.s_addr = name_ip.s_addr; /* Fix this ... */ + + bzero((char *)&p, sizeof(p)); + + *count = 0; + + nmb->header.name_trn_id = generate_trn_id(); + nmb->header.opcode = opcode; + nmb->header.response = False; + nmb->header.nm_flags.bcast = False; + nmb->header.nm_flags.recursion_available = False; + nmb->header.nm_flags.recursion_desired = True; /* ? */ + nmb->header.nm_flags.trunc = False; + nmb->header.nm_flags.authoritative = True; + + nmb->header.qdcount = 1; + nmb->header.ancount = 0; + nmb->header.nscount = 0; + nmb->header.arcount = 1; + + make_nmb_name(&nmb->question.question_name, name, name_type); + + nmb->question.question_type = 0x20; + nmb->question.question_class = 0x1; + + /* Now, create the additional stuff for a registration request */ + + if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) { + + DEBUG(0, ("name_register: malloc fail for additional record.\n")); + return False; + + } + + bzero((char *)nmb->additional, sizeof(struct res_rec)); + + nmb->additional->rr_name = nmb->question.question_name; + nmb->additional->rr_type = RR_TYPE_NB; + nmb->additional->rr_class = RR_CLASS_IN; + + /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */ + if (nmb->header.nm_flags.bcast) + nmb->additional->ttl = PERMANENT_TTL; + else + nmb->additional->ttl = lp_max_ttl(); + + nmb->additional->rdlength = 6; + + nmb->additional->rdata[0] = NB_MFLAG & 0xFF; + + /* Set the address for the name we are registering. */ + putip(&nmb->additional->rdata[2], ®ister_ip); + + p.ip = to_ip; + p.port = NMB_PORT; + p.fd = fd; + p.timestamp = time(NULL); + p.packet_type = NMB_PACKET; + + GetTimeOfDay(&tval); + + if (!send_packet(&p)) + return False; + + retries--; + + if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) { + debug_nmb_packet(p2); + free(p2); /* No memory leaks ... */ + } + + return True; +} /**************************************************************************** Do a netbios name query to find someones IP. @@ -456,6 +546,65 @@ void endlmhosts(FILE *fp) fclose(fp); } +BOOL name_register_wins(const char *name, int name_type) +{ + int sock, i, return_count; + int num_interfaces = iface_count(); + struct in_addr sendto_ip; + + /* + * Do a broadcast register ... + */ + + if (!lp_wins_server()) + return False; + + DEBUG(4, ("name_register_wins:Registering my name %s on %s\n", name, lp_wins_server())); + + sock = open_socket_in(SOCK_DGRAM, 0, 3, + interpret_addr("0.0.0.0"), True); + + if (sock == -1) return False; + + set_socket_options(sock, "SO_BROADCAST"); + + sendto_ip.s_addr = inet_addr(lp_wins_server()); + + if (num_interfaces > 1) { + + for (i = 0; i < num_interfaces; i++) { + + if (!name_register(sock, name, name_type, *iface_n_ip(i), + NMB_NAME_MULTIHOMED_REG_OPCODE, + True, sendto_ip, &return_count)) { + + close(sock); + return False; + + } + + } + + } + else { + + if (!name_register(sock, name, name_type, *iface_n_ip(0), + NMB_NAME_REG_OPCODE, + True, sendto_ip, &return_count)) { + + close(sock); + return False; + + } + + } + + close(sock); + + return True; + +} + /******************************************************** Resolve via "bcast" method. *********************************************************/ @@ -623,7 +772,7 @@ static BOOL resolve_hosts(const char *name, DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name)); - if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) { + if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) { struct in_addr return_ip; putip((char *)&return_ip,(char *)hp->h_addr); *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr)); diff --git a/source/libsmb/pwd_cache.c b/source/libsmb/pwd_cache.c index 26b1d192f09..420b49ed2e7 100644 --- a/source/libsmb/pwd_cache.c +++ b/source/libsmb/pwd_cache.c @@ -103,11 +103,21 @@ void pwd_read(struct pwd_info *pwd, char *passwd_report, BOOL do_encrypt) user_pass = (char*)getpass(passwd_report); + /* + * Do not assume that an empty string is a NULL password. + * If you do this will break the session key generation for + * and account with an emtpy password. If you wish to use + * a NULL password, use the -N option to smbclient and rpcclient + * --jerry + */ +#if 0 if (user_pass == NULL || user_pass[0] == 0) { pwd_set_nullpwd(pwd); } else if (do_encrypt) +#endif + if (do_encrypt) { pwd_make_lm_nt_16(pwd, user_pass); } diff --git a/source/libsmb/smbdes.c b/source/libsmb/smbdes.c index d0e1c6e85fb..7e8a9a5b89e 100644 --- a/source/libsmb/smbdes.c +++ b/source/libsmb/smbdes.c @@ -381,7 +381,7 @@ void SamOEMhash( unsigned char *data, unsigned char *key, int val) s_box[ind] = s_box[j]; s_box[j] = tc; } - for( ind = 0; ind < (val ? 516 : 16); ind++) + for( ind = 0; ind < val; ind++) { unsigned char tc; unsigned char t; diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c index caf92567879..7efb2bb9b31 100644 --- a/source/libsmb/smbencrypt.c +++ b/source/libsmb/smbencrypt.c @@ -223,7 +223,7 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[ DEBUG(100,("make_oem_passwd_hash\n")); dump_data(100, data, 516); #endif - SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True); + SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516); return True; } diff --git a/source/libsmb/unexpected.c b/source/libsmb/unexpected.c index 6c5dd611a9c..4aa566de5b2 100644 --- a/source/libsmb/unexpected.c +++ b/source/libsmb/unexpected.c @@ -49,7 +49,7 @@ void unexpected_packet(struct packet_struct *p) int len=0; if (!tdbd) { - tdbd = tdb_open(lock_path("unexpected.tdb"), 1, + tdbd = tdb_open_log(lock_path("unexpected.tdb"), 1, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); if (!tdbd) { @@ -151,7 +151,7 @@ struct packet_struct *receive_unexpected(enum packet_type packet_type, int id, { TDB_CONTEXT *tdb2; - tdb2 = tdb_open(lock_path("unexpected.tdb"), 0, 0, O_RDONLY, 0); + tdb2 = tdb_open_log(lock_path("unexpected.tdb"), 0, 0, O_RDONLY, 0); if (!tdb2) return NULL; matched_packet = NULL; -- cgit