root/source3/libads/cldap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. send_cldap_netlogon
  2. recv_cldap_netlogon
  3. ads_cldap_netlogon
  4. ads_cldap_netlogon_5

   1 /* 
   2    Samba Unix/Linux SMB client library 
   3    net ads cldap functions 
   4    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
   5    Copyright (C) 2003 Jim McDonough (jmcd@us.ibm.com)
   6    Copyright (C) 2008 Guenther Deschner (gd@samba.org)
   7 
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12 
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17 
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  
  20 */
  21 
  22 #include "includes.h"
  23 
  24 /*
  25   do a cldap netlogon query
  26 */
  27 static int send_cldap_netlogon(TALLOC_CTX *mem_ctx, int sock, const char *domain,
     /* [<][>][^][v][top][bottom][index][help] */
  28                                const char *hostname, unsigned ntversion)
  29 {
  30         ASN1_DATA *data;
  31         char ntver[4];
  32 #ifdef CLDAP_USER_QUERY
  33         char aac[4];
  34 
  35         SIVAL(aac, 0, 0x00000180);
  36 #endif
  37         SIVAL(ntver, 0, ntversion);
  38 
  39         data = asn1_init(mem_ctx);
  40         if (data == NULL) {
  41                 return -1;
  42         }
  43 
  44         asn1_push_tag(data,ASN1_SEQUENCE(0));
  45         asn1_write_Integer(data, 4);
  46         asn1_push_tag(data, ASN1_APPLICATION(3));
  47         asn1_write_OctetString(data, NULL, 0);
  48         asn1_write_enumerated(data, 0);
  49         asn1_write_enumerated(data, 0);
  50         asn1_write_Integer(data, 0);
  51         asn1_write_Integer(data, 0);
  52         asn1_write_BOOLEAN(data, False);
  53         asn1_push_tag(data, ASN1_CONTEXT(0));
  54 
  55         if (domain) {
  56                 asn1_push_tag(data, ASN1_CONTEXT(3));
  57                 asn1_write_OctetString(data, "DnsDomain", 9);
  58                 asn1_write_OctetString(data, domain, strlen(domain));
  59                 asn1_pop_tag(data);
  60         }
  61 
  62         asn1_push_tag(data, ASN1_CONTEXT(3));
  63         asn1_write_OctetString(data, "Host", 4);
  64         asn1_write_OctetString(data, hostname, strlen(hostname));
  65         asn1_pop_tag(data);
  66 
  67 #ifdef CLDAP_USER_QUERY
  68         asn1_push_tag(data, ASN1_CONTEXT(3));
  69         asn1_write_OctetString(data, "User", 4);
  70         asn1_write_OctetString(data, "SAMBA$", 6);
  71         asn1_pop_tag(data);
  72 
  73         asn1_push_tag(data, ASN1_CONTEXT(3));
  74         asn1_write_OctetString(data, "AAC", 4);
  75         asn1_write_OctetString(data, aac, 4);
  76         asn1_pop_tag(data);
  77 #endif
  78 
  79         asn1_push_tag(data, ASN1_CONTEXT(3));
  80         asn1_write_OctetString(data, "NtVer", 5);
  81         asn1_write_OctetString(data, ntver, 4);
  82         asn1_pop_tag(data);
  83 
  84         asn1_pop_tag(data);
  85 
  86         asn1_push_tag(data,ASN1_SEQUENCE(0));
  87         asn1_write_OctetString(data, "NetLogon", 8);
  88         asn1_pop_tag(data);
  89         asn1_pop_tag(data);
  90         asn1_pop_tag(data);
  91 
  92         if (data->has_error) {
  93                 DEBUG(2,("Failed to build cldap netlogon at offset %d\n", (int)data->ofs));
  94                 asn1_free(data);
  95                 return -1;
  96         }
  97 
  98         if (write(sock, data->data, data->length) != (ssize_t)data->length) {
  99                 DEBUG(2,("failed to send cldap query (%s)\n", strerror(errno)));
 100                 asn1_free(data);
 101                 return -1;
 102         }
 103 
 104         asn1_free(data);
 105 
 106         return 0;
 107 }
 108 
 109 /*
 110   receive a cldap netlogon reply
 111 */
 112 static int recv_cldap_netlogon(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 113                                int sock,
 114                                uint32_t nt_version,
 115                                struct netlogon_samlogon_response **reply)
 116 {
 117         int ret;
 118         ASN1_DATA *data;
 119         DATA_BLOB blob = data_blob_null;
 120         DATA_BLOB os1 = data_blob_null;
 121         DATA_BLOB os2 = data_blob_null;
 122         DATA_BLOB os3 = data_blob_null;
 123         int i1;
 124         struct netlogon_samlogon_response *r = NULL;
 125         NTSTATUS status;
 126 
 127         fd_set r_fds;
 128         struct timeval timeout;
 129 
 130         blob = data_blob(NULL, 8192);
 131         if (blob.data == NULL) {
 132                 DEBUG(1, ("data_blob failed\n"));
 133                 errno = ENOMEM;
 134                 return -1;
 135         }
 136 
 137         FD_ZERO(&r_fds);
 138         FD_SET(sock, &r_fds);
 139 
 140         /*
 141          * half the time of a regular ldap timeout, not less than 3 seconds.
 142          */
 143         timeout.tv_sec = MAX(3,lp_ldap_timeout()/2);
 144         timeout.tv_usec = 0;
 145 
 146         ret = sys_select(sock+1, &r_fds, NULL, NULL, &timeout);
 147         if (ret == -1) {
 148                 DEBUG(10, ("select failed: %s\n", strerror(errno)));
 149                 data_blob_free(&blob);
 150                 return -1;
 151         }
 152 
 153         if (ret == 0) {
 154                 DEBUG(1,("no reply received to cldap netlogon "
 155                         "(select timeout %u sec)\n",
 156                         (unsigned int)timeout.tv_sec));
 157                 data_blob_free(&blob);
 158                 return -1;
 159         }
 160 
 161         ret = read(sock, blob.data, blob.length);
 162         if (ret <= 0) {
 163                 DEBUG(1,("no reply received to cldap netlogon "
 164                         "(ret = %d: Error = %s)\n",
 165                         ret,
 166                         ret == -1 ? strerror(errno) : "" ));
 167                 data_blob_free(&blob);
 168                 return -1;
 169         }
 170         blob.length = ret;
 171 
 172         data = asn1_init(mem_ctx);
 173         if (data == NULL) {
 174                 data_blob_free(&blob);
 175                 return -1;
 176         }
 177 
 178         asn1_load(data, blob);
 179         asn1_start_tag(data, ASN1_SEQUENCE(0));
 180         asn1_read_Integer(data, &i1);
 181         asn1_start_tag(data, ASN1_APPLICATION(4));
 182         asn1_read_OctetString(data, NULL, &os1);
 183         asn1_start_tag(data, ASN1_SEQUENCE(0));
 184         asn1_start_tag(data, ASN1_SEQUENCE(0));
 185         asn1_read_OctetString(data, NULL, &os2);
 186         asn1_start_tag(data, ASN1_SET);
 187         asn1_read_OctetString(data, NULL, &os3);
 188         asn1_end_tag(data);
 189         asn1_end_tag(data);
 190         asn1_end_tag(data);
 191         asn1_end_tag(data);
 192         asn1_end_tag(data);
 193 
 194         if (data->has_error) {
 195                 data_blob_free(&blob);
 196                 data_blob_free(&os1);
 197                 data_blob_free(&os2);
 198                 data_blob_free(&os3);
 199                 asn1_free(data);
 200                 DEBUG(1,("Failed to parse cldap reply\n"));
 201                 return -1;
 202         }
 203 
 204         r = TALLOC_ZERO_P(mem_ctx, struct netlogon_samlogon_response);
 205         if (!r) {
 206                 errno = ENOMEM;
 207                 data_blob_free(&os1);
 208                 data_blob_free(&os2);
 209                 data_blob_free(&os3);
 210                 data_blob_free(&blob);
 211                 asn1_free(data);
 212                 return -1;
 213         }
 214 
 215         status = pull_netlogon_samlogon_response(&os3, mem_ctx, NULL, r);
 216         if (!NT_STATUS_IS_OK(status)) {
 217                 data_blob_free(&os1);
 218                 data_blob_free(&os2);
 219                 data_blob_free(&os3);
 220                 data_blob_free(&blob);
 221                 asn1_free(data);
 222                 TALLOC_FREE(r);
 223                 return -1;
 224         }
 225 
 226         map_netlogon_samlogon_response(r);
 227 
 228         data_blob_free(&os1);
 229         data_blob_free(&os2);
 230         data_blob_free(&os3);
 231         data_blob_free(&blob);
 232 
 233         asn1_free(data);
 234 
 235         if (reply) {
 236                 *reply = r;
 237         } else {
 238                 TALLOC_FREE(r);
 239         }
 240 
 241         return 0;
 242 }
 243 
 244 /*******************************************************************
 245   do a cldap netlogon query.  Always 389/udp
 246 *******************************************************************/
 247 
 248 bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 249                         const char *server,
 250                         const char *realm,
 251                         uint32_t nt_version,
 252                         struct netlogon_samlogon_response **reply)
 253 {
 254         int sock;
 255         int ret;
 256 
 257         sock = open_udp_socket(server, LDAP_PORT );
 258         if (sock == -1) {
 259                 DEBUG(2,("ads_cldap_netlogon: Failed to open udp socket to %s. "
 260                         "Error %s\n",
 261                         server,
 262                         strerror(errno) ));
 263                 return False;
 264         }
 265 
 266         ret = send_cldap_netlogon(mem_ctx, sock, realm, global_myname(), nt_version);
 267         if (ret != 0) {
 268                 close(sock);
 269                 return False;
 270         }
 271         ret = recv_cldap_netlogon(mem_ctx, sock, nt_version, reply);
 272         close(sock);
 273 
 274         if (ret == -1) {
 275                 return False;
 276         }
 277 
 278         return True;
 279 }
 280 
 281 /*******************************************************************
 282   do a cldap netlogon query.  Always 389/udp
 283 *******************************************************************/
 284 
 285 bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 286                           const char *server,
 287                           const char *realm,
 288                           struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5)
 289 {
 290         uint32_t nt_version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
 291         struct netlogon_samlogon_response *reply = NULL;
 292         bool ret;
 293 
 294         ret = ads_cldap_netlogon(mem_ctx, server, realm, nt_version, &reply);
 295         if (!ret) {
 296                 return false;
 297         }
 298 
 299         if (reply->ntver != NETLOGON_NT_VERSION_5EX) {
 300                 DEBUG(0,("ads_cldap_netlogon_5: nt_version mismatch: 0x%08x\n",
 301                         reply->ntver));
 302                 return false;
 303         }
 304 
 305         *reply5 = reply->data.nt5_ex;
 306 
 307         return true;
 308 }

/* [<][>][^][v][top][bottom][index][help] */