Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/libsmb/clidgram.c

    r596 r745  
    1010   the Free Software Foundation; either version 3 of the License, or
    1111   (at your option) any later version.
    12    
     12
    1313   This program is distributed in the hope that it will be useful,
    1414   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1515   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1616   GNU General Public License for more details.
    17    
     17
    1818   You should have received a copy of the GNU General Public License
    1919   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2121
    2222#include "includes.h"
     23#include "libsmb/libsmb.h"
     24#include "../lib/util/tevent_ntstatus.h"
     25#include "libsmb/clidgram.h"
     26#include "libsmb/nmblib.h"
     27#include "messages.h"
    2328
    2429/*
     
    2631 */
    2732
    28 static bool cli_send_mailslot(struct messaging_context *msg_ctx,
    29                        bool unique, const char *mailslot,
     33static bool cli_prep_mailslot(bool unique, const char *mailslot,
    3034                       uint16 priority,
    3135                       char *buf, int len,
    3236                       const char *srcname, int src_type,
    3337                       const char *dstname, int dest_type,
    34                        const struct sockaddr_storage *dest_ss)
    35 {
    36         struct packet_struct p;
    37         struct dgram_packet *dgram = &p.packet.dgram;
     38                       const struct sockaddr_storage *dest_ss,
     39                       int dgm_id,
     40                       struct packet_struct *p)
     41{
     42        struct dgram_packet *dgram = &p->packet.dgram;
    3843        char *ptr, *p2;
    3944        char tmp[4];
    40         pid_t nmbd_pid;
    4145        char addr[INET6_ADDRSTRLEN];
    4246
    43         if ((nmbd_pid = pidfile_pid("nmbd")) == 0) {
    44                 DEBUG(3, ("No nmbd found\n"));
    45                 return False;
    46         }
    47 
    48         if (dest_ss->ss_family != AF_INET) {
    49                 DEBUG(3, ("cli_send_mailslot: can't send to IPv6 address.\n"));
    50                 return false;
    51         }
    52 
    53         memset((char *)&p, '\0', sizeof(p));
     47        ZERO_STRUCTP(p);
    5448
    5549        /*
     
    6256        dgram->header.flags.first = True;
    6357        dgram->header.flags.more = False;
    64         dgram->header.dgm_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) +
    65                 ((unsigned)sys_getpid()%(unsigned)100);
     58        dgram->header.dgm_id = dgm_id;
    6659        /* source ip is filled by nmbd */
    6760        dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
     
    10598        dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
    10699
    107         p.packet_type = DGRAM_PACKET;
    108         p.ip = ((const struct sockaddr_in *)dest_ss)->sin_addr;
    109         p.timestamp = time(NULL);
     100        p->packet_type = DGRAM_PACKET;
     101        p->ip = ((const struct sockaddr_in *)dest_ss)->sin_addr;
     102        p->timestamp = time(NULL);
    110103
    111104        DEBUG(4,("send_mailslot: Sending to mailslot %s from %s ",
     
    115108        DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), addr));
    116109
    117         return NT_STATUS_IS_OK(messaging_send_buf(msg_ctx,
    118                                                   pid_to_procid(nmbd_pid),
    119                                                   MSG_SEND_PACKET,
    120                                                   (uint8 *)&p, sizeof(p)));
    121 }
    122 
    123 static const char *mailslot_name(TALLOC_CTX *mem_ctx, struct in_addr dc_ip)
     110        return true;
     111}
     112
     113static char *mailslot_name(TALLOC_CTX *mem_ctx, struct in_addr dc_ip)
    124114{
    125115        return talloc_asprintf(mem_ctx, "%s%X",
     
    127117}
    128118
    129 bool send_getdc_request(TALLOC_CTX *mem_ctx,
    130                         struct messaging_context *msg_ctx,
    131                         struct sockaddr_storage *dc_ss,
    132                         const char *domain_name,
    133                         const DOM_SID *sid,
    134                         uint32_t nt_version)
    135 {
    136         struct in_addr dc_ip;
    137         const char *my_acct_name = NULL;
    138         const char *my_mailslot = NULL;
     119static bool prep_getdc_request(const struct sockaddr_storage *dc_ss,
     120                               const char *domain_name,
     121                               const struct dom_sid *sid,
     122                               uint32_t nt_version,
     123                               const char *my_mailslot,
     124                               int dgm_id,
     125                               struct packet_struct *p)
     126{
     127        TALLOC_CTX *frame = talloc_stackframe();
     128        const char *my_acct_name;
    139129        struct nbt_netlogon_packet packet;
    140130        struct NETLOGON_SAM_LOGON_REQUEST *s;
    141131        enum ndr_err_code ndr_err;
    142         DATA_BLOB blob;
     132        DATA_BLOB blob = data_blob_null;
    143133        struct dom_sid my_sid;
     134        bool ret = false;
    144135
    145136        ZERO_STRUCT(packet);
    146137        ZERO_STRUCT(my_sid);
    147138
    148         if (dc_ss->ss_family != AF_INET) {
    149                 return false;
    150         }
    151 
    152         if (sid) {
     139        if (sid != NULL) {
    153140                my_sid = *sid;
    154141        }
    155142
    156         dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
    157         my_mailslot = mailslot_name(mem_ctx, dc_ip);
    158         if (!my_mailslot) {
    159                 return false;
    160         }
    161 
    162         my_acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname());
    163         if (!my_acct_name) {
    164                 return false;
     143        my_acct_name = talloc_asprintf(talloc_tos(), "%s$", global_myname());
     144        if (my_acct_name == NULL) {
     145                goto fail;
    165146        }
    166147
     
    182163        }
    183164
    184         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &packet,
     165        ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &packet,
    185166                       (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_packet);
    186167        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    187                 return false;
    188         }
    189 
    190         return cli_send_mailslot(msg_ctx,
    191                                  false, NBT_MAILSLOT_NTLOGON, 0,
    192                                  (char *)blob.data, blob.length,
    193                                  global_myname(), 0, domain_name, 0x1c,
    194                                  dc_ss);
    195 }
    196 
    197 bool receive_getdc_response(TALLOC_CTX *mem_ctx,
    198                             struct sockaddr_storage *dc_ss,
    199                             const char *domain_name,
    200                             uint32_t *nt_version,
    201                             const char **dc_name,
    202                             struct netlogon_samlogon_response **_r)
    203 {
    204         struct packet_struct *packet;
    205         const char *my_mailslot = NULL;
    206         struct in_addr dc_ip;
     168                goto fail;
     169        }
     170
     171        ret = cli_prep_mailslot(false, NBT_MAILSLOT_NTLOGON, 0,
     172                                (char *)blob.data, blob.length,
     173                                global_myname(), 0, domain_name, 0x1c,
     174                                dc_ss, dgm_id, p);
     175fail:
     176        TALLOC_FREE(frame);
     177        return ret;
     178}
     179
     180static bool parse_getdc_response(
     181        struct packet_struct *packet,
     182        TALLOC_CTX *mem_ctx,
     183        const char *domain_name,
     184        uint32_t *nt_version,
     185        const char **dc_name,
     186        struct netlogon_samlogon_response **samlogon_response)
     187{
    207188        DATA_BLOB blob;
    208         struct netlogon_samlogon_response r;
     189        struct netlogon_samlogon_response *r;
    209190        union dgram_message_body p;
    210191        enum ndr_err_code ndr_err;
     
    214195        const char *returned_domain = NULL;
    215196
    216         if (dc_ss->ss_family != AF_INET) {
    217                 return false;
    218         }
    219 
    220         dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
    221 
    222         my_mailslot = mailslot_name(mem_ctx, dc_ip);
    223         if (!my_mailslot) {
    224                 return false;
    225         }
    226 
    227         packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
    228 
    229         if (packet == NULL) {
    230                 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
    231                 return False;
    232         }
    233 
    234         DEBUG(5, ("Received packet for %s\n", my_mailslot));
    235 
    236197        blob = data_blob_const(packet->packet.dgram.data,
    237198                               packet->packet.dgram.datasize);
    238 
    239199        if (blob.length < 4) {
    240                 DEBUG(0,("invalid length: %d\n", (int)blob.length));
    241                 free_packet(packet);
     200                DEBUG(1, ("invalid length: %d\n", (int)blob.length));
    242201                return false;
    243202        }
    244203
    245204        if (RIVAL(blob.data,0) != DGRAM_SMB) {
    246                 DEBUG(0,("invalid packet\n"));
    247                 free_packet(packet);
     205                DEBUG(1, ("invalid packet\n"));
    248206                return false;
    249207        }
     
    252210        blob.length -= 4;
    253211
    254         ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, NULL, &p, DGRAM_SMB,
     212        ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, &p, DGRAM_SMB,
    255213                       (ndr_pull_flags_fn_t)ndr_pull_dgram_smb_packet);
    256214        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    257                 DEBUG(0,("failed to parse packet\n"));
    258                 free_packet(packet);
     215                DEBUG(1, ("failed to parse packet\n"));
    259216                return false;
    260217        }
    261218
    262219        if (p.smb.smb_command != SMB_TRANSACTION) {
    263                 DEBUG(0,("invalid smb_command: %d\n", p.smb.smb_command));
    264                 free_packet(packet);
     220                DEBUG(1, ("invalid smb_command: %d\n", p.smb.smb_command));
    265221                return false;
    266222        }
     
    272228        blob = p.smb.body.trans.data;
    273229
    274         ZERO_STRUCT(r);
    275 
    276         status = pull_netlogon_samlogon_response(&blob, mem_ctx, NULL, &r);
     230        r = TALLOC_ZERO_P(mem_ctx, struct netlogon_samlogon_response);
     231        if (!r) {
     232                return false;
     233        }
     234
     235        status = pull_netlogon_samlogon_response(&blob, r, r);
    277236        if (!NT_STATUS_IS_OK(status)) {
    278                 free_packet(packet);
    279                 return false;
    280         }
    281 
    282         map_netlogon_samlogon_response(&r);
     237                TALLOC_FREE(r);
     238                return false;
     239        }
     240
     241        map_netlogon_samlogon_response(r);
    283242
    284243        /* do we still need this ? */
    285         *nt_version = r.ntver;
    286 
    287         returned_domain = r.data.nt5_ex.domain;
    288         returned_dc = r.data.nt5_ex.pdc_name;
     244        *nt_version = r->ntver;
     245
     246        returned_domain = r->data.nt5_ex.domain_name;
     247        returned_dc = r->data.nt5_ex.pdc_name;
    289248
    290249        if (!strequal(returned_domain, domain_name)) {
    291250                DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
    292251                          domain_name, returned_domain));
    293                 free_packet(packet);
    294                 return false;
    295         }
     252                TALLOC_FREE(r);
     253                return false;
     254        }
     255
     256        if (*returned_dc == '\\') returned_dc += 1;
     257        if (*returned_dc == '\\') returned_dc += 1;
    296258
    297259        *dc_name = talloc_strdup(mem_ctx, returned_dc);
    298260        if (!*dc_name) {
    299                 free_packet(packet);
    300                 return false;
    301         }
    302 
    303         if (**dc_name == '\\')  *dc_name += 1;
    304         if (**dc_name == '\\')  *dc_name += 1;
    305 
    306         if (_r) {
    307                 *_r = (struct netlogon_samlogon_response *)talloc_memdup(
    308                         mem_ctx, &r, sizeof(struct netlogon_samlogon_response));
    309                 if (!*_r) {
    310                 free_packet(packet);
    311                         return false;
    312                 }
     261                TALLOC_FREE(r);
     262                return false;
     263        }
     264
     265        if (samlogon_response) {
     266                *samlogon_response = r;
     267        } else {
     268                TALLOC_FREE(r);
    313269        }
    314270
     
    316272                   *dc_name, returned_domain));
    317273
    318         free_packet(packet);
    319274        return True;
    320275}
     276
     277struct nbt_getdc_state {
     278        struct tevent_context *ev;
     279        struct messaging_context *msg_ctx;
     280        struct nb_packet_reader *reader;
     281        const char *my_mailslot;
     282        pid_t nmbd_pid;
     283
     284        const struct sockaddr_storage *dc_addr;
     285        const char *domain_name;
     286        const struct dom_sid *sid;
     287        uint32_t nt_version;
     288        const char *dc_name;
     289        struct netlogon_samlogon_response *samlogon_response;
     290
     291        struct packet_struct p;
     292};
     293
     294static void nbt_getdc_got_reader(struct tevent_req *subreq);
     295static void nbt_getdc_got_response(struct tevent_req *subreq);
     296
     297struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
     298                                  struct tevent_context *ev,
     299                                  struct messaging_context *msg_ctx,
     300                                  const struct sockaddr_storage *dc_addr,
     301                                  const char *domain_name,
     302                                  const struct dom_sid *sid,
     303                                  uint32_t nt_version)
     304{
     305        struct tevent_req *req, *subreq;
     306        struct nbt_getdc_state *state;
     307        uint16_t dgm_id;
     308
     309        req = tevent_req_create(mem_ctx, &state, struct nbt_getdc_state);
     310        if (req == NULL) {
     311                return NULL;
     312        }
     313        state->ev = ev;
     314        state->msg_ctx = msg_ctx;
     315        state->dc_addr = dc_addr;
     316        state->domain_name = domain_name;
     317        state->sid = sid;
     318        state->nt_version = nt_version;
     319
     320        if (dc_addr->ss_family != AF_INET) {
     321                tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
     322                return tevent_req_post(req, ev);
     323        }
     324        state->my_mailslot = mailslot_name(
     325                state, ((struct sockaddr_in *)dc_addr)->sin_addr);
     326        if (tevent_req_nomem(state->my_mailslot, req)) {
     327                return tevent_req_post(req, ev);
     328        }
     329        state->nmbd_pid = pidfile_pid("nmbd");
     330        if (state->nmbd_pid == 0) {
     331                DEBUG(3, ("No nmbd found\n"));
     332                tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
     333                return tevent_req_post(req, ev);
     334        }
     335
     336        generate_random_buffer((uint8_t *)(void *)&dgm_id, sizeof(dgm_id));
     337
     338        if (!prep_getdc_request(dc_addr, domain_name, sid, nt_version,
     339                                state->my_mailslot, dgm_id & 0x7fff,
     340                                &state->p)) {
     341                DEBUG(3, ("prep_getdc_request failed\n"));
     342                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     343                return tevent_req_post(req, ev);
     344        }
     345
     346        subreq = nb_packet_reader_send(state, ev, DGRAM_PACKET, -1,
     347                                       state->my_mailslot);
     348        if (tevent_req_nomem(subreq, req)) {
     349                return tevent_req_post(req, ev);
     350        }
     351        tevent_req_set_callback(subreq, nbt_getdc_got_reader, req);
     352        return req;
     353}
     354
     355static void nbt_getdc_got_reader(struct tevent_req *subreq)
     356{
     357        struct tevent_req *req = tevent_req_callback_data(
     358                subreq, struct tevent_req);
     359        struct nbt_getdc_state *state = tevent_req_data(
     360                req, struct nbt_getdc_state);
     361        NTSTATUS status;
     362
     363        status = nb_packet_reader_recv(subreq, state, &state->reader);
     364        TALLOC_FREE(subreq);
     365        if (tevent_req_nterror(req, status)) {
     366                DEBUG(10, ("nb_packet_reader_recv returned %s\n",
     367                           nt_errstr(status)));
     368                return;
     369        }
     370
     371        status = messaging_send_buf(
     372                state->msg_ctx, pid_to_procid(state->nmbd_pid),
     373                MSG_SEND_PACKET, (uint8_t *)&state->p, sizeof(state->p));
     374
     375        if (tevent_req_nterror(req, status)) {
     376                DEBUG(10, ("messaging_send_buf returned %s\n",
     377                           nt_errstr(status)));
     378                return;
     379        }
     380        subreq = nb_packet_read_send(state, state->ev, state->reader);
     381        if (tevent_req_nomem(subreq, req)) {
     382                return;
     383        }
     384        tevent_req_set_callback(subreq, nbt_getdc_got_response, req);
     385}
     386
     387static void nbt_getdc_got_response(struct tevent_req *subreq)
     388{
     389        struct tevent_req *req = tevent_req_callback_data(
     390                subreq, struct tevent_req);
     391        struct nbt_getdc_state *state = tevent_req_data(
     392                req, struct nbt_getdc_state);
     393        struct packet_struct *p;
     394        NTSTATUS status;
     395        bool ret;
     396
     397        status = nb_packet_read_recv(subreq, &p);
     398        TALLOC_FREE(subreq);
     399        if (tevent_req_nterror(req, status)) {
     400                return;
     401        }
     402
     403        ret = parse_getdc_response(p, state, state->domain_name,
     404                                   &state->nt_version, &state->dc_name,
     405                                   &state->samlogon_response);
     406        free_packet(p);
     407        if (!ret) {
     408                tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     409                return;
     410        }
     411        tevent_req_done(req);
     412}
     413
     414NTSTATUS nbt_getdc_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     415                        uint32_t *nt_version, const char **dc_name,
     416                        struct netlogon_samlogon_response **samlogon_response)
     417{
     418        struct nbt_getdc_state *state = tevent_req_data(
     419                req, struct nbt_getdc_state);
     420        NTSTATUS status;
     421
     422        if (tevent_req_is_nterror(req, &status)) {
     423                return status;
     424        }
     425        if (nt_version != NULL) {
     426                *nt_version = state->nt_version;
     427        }
     428        if (dc_name != NULL) {
     429                *dc_name = talloc_move(mem_ctx, &state->dc_name);
     430        }
     431        if (samlogon_response != NULL) {
     432                *samlogon_response = talloc_move(
     433                        mem_ctx, &state->samlogon_response);
     434        }
     435        return NT_STATUS_OK;
     436}
     437
     438NTSTATUS nbt_getdc(struct messaging_context *msg_ctx,
     439                   const struct sockaddr_storage *dc_addr,
     440                   const char *domain_name,
     441                   const struct dom_sid *sid,
     442                   uint32_t nt_version,
     443                   TALLOC_CTX *mem_ctx,
     444                   uint32_t *pnt_version,
     445                   const char **dc_name,
     446                   struct netlogon_samlogon_response **samlogon_response)
     447{
     448        TALLOC_CTX *frame = talloc_stackframe();
     449        struct tevent_context *ev;
     450        struct tevent_req *req;
     451        NTSTATUS status = NT_STATUS_NO_MEMORY;
     452
     453        ev = tevent_context_init(frame);
     454        if (ev == NULL) {
     455                goto fail;
     456        }
     457        req = nbt_getdc_send(ev, ev, msg_ctx, dc_addr, domain_name,
     458                             sid, nt_version);
     459        if (req == NULL) {
     460                goto fail;
     461        }
     462        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     463                goto fail;
     464        }
     465        status = nbt_getdc_recv(req, mem_ctx, pnt_version, dc_name,
     466                                samlogon_response);
     467 fail:
     468        TALLOC_FREE(frame);
     469        return status;
     470}
Note: See TracChangeset for help on using the changeset viewer.