00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "includes.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 static unsigned pull_netlogon_string(char *ret, const char *ptr,
00048 const char *data)
00049 {
00050 char *pret = ret;
00051 int followed_ptr = 0;
00052 unsigned ret_len = 0;
00053
00054 memset(pret, 0, MAX_DNS_LABEL);
00055 do {
00056 if ((*ptr & 0xc0) == 0xc0) {
00057 uint16 len;
00058
00059 if (!followed_ptr) {
00060 ret_len += 2;
00061 followed_ptr = 1;
00062 }
00063 len = ((ptr[0] & 0x3f) << 8) | ptr[1];
00064 ptr = data + len;
00065 } else if (*ptr) {
00066 uint8 len = (uint8)*(ptr++);
00067
00068 if ((pret - ret + len + 1) >= MAX_DNS_LABEL) {
00069 DEBUG(1,("DC returning too long DNS name\n"));
00070 return 0;
00071 }
00072
00073 if (pret != ret) {
00074 *pret = '.';
00075 pret++;
00076 }
00077 memcpy(pret, ptr, len);
00078 pret += len;
00079 ptr += len;
00080
00081 if (!followed_ptr) {
00082 ret_len += (len + 1);
00083 }
00084 }
00085 } while (*ptr);
00086
00087 return followed_ptr ? ret_len : ret_len + 1;
00088 }
00089
00090
00091
00092
00093 static int send_cldap_netlogon(int sock, const char *domain,
00094 const char *hostname, unsigned ntversion)
00095 {
00096 ASN1_DATA data;
00097 char ntver[4];
00098 #ifdef CLDAP_USER_QUERY
00099 char aac[4];
00100
00101 SIVAL(aac, 0, 0x00000180);
00102 #endif
00103 SIVAL(ntver, 0, ntversion);
00104
00105 memset(&data, 0, sizeof(data));
00106
00107 asn1_push_tag(&data,ASN1_SEQUENCE(0));
00108 asn1_write_Integer(&data, 4);
00109 asn1_push_tag(&data, ASN1_APPLICATION(3));
00110 asn1_write_OctetString(&data, NULL, 0);
00111 asn1_write_enumerated(&data, 0);
00112 asn1_write_enumerated(&data, 0);
00113 asn1_write_Integer(&data, 0);
00114 asn1_write_Integer(&data, 0);
00115 asn1_write_BOOLEAN2(&data, False);
00116 asn1_push_tag(&data, ASN1_CONTEXT(0));
00117
00118 if (domain) {
00119 asn1_push_tag(&data, ASN1_CONTEXT(3));
00120 asn1_write_OctetString(&data, "DnsDomain", 9);
00121 asn1_write_OctetString(&data, domain, strlen(domain));
00122 asn1_pop_tag(&data);
00123 }
00124
00125 asn1_push_tag(&data, ASN1_CONTEXT(3));
00126 asn1_write_OctetString(&data, "Host", 4);
00127 asn1_write_OctetString(&data, hostname, strlen(hostname));
00128 asn1_pop_tag(&data);
00129
00130 #ifdef CLDAP_USER_QUERY
00131 asn1_push_tag(&data, ASN1_CONTEXT(3));
00132 asn1_write_OctetString(&data, "User", 4);
00133 asn1_write_OctetString(&data, "SAMBA$", 6);
00134 asn1_pop_tag(&data);
00135
00136 asn1_push_tag(&data, ASN1_CONTEXT(3));
00137 asn1_write_OctetString(&data, "AAC", 4);
00138 asn1_write_OctetString(&data, aac, 4);
00139 asn1_pop_tag(&data);
00140 #endif
00141
00142 asn1_push_tag(&data, ASN1_CONTEXT(3));
00143 asn1_write_OctetString(&data, "NtVer", 5);
00144 asn1_write_OctetString(&data, ntver, 4);
00145 asn1_pop_tag(&data);
00146
00147 asn1_pop_tag(&data);
00148
00149 asn1_push_tag(&data,ASN1_SEQUENCE(0));
00150 asn1_write_OctetString(&data, "NetLogon", 8);
00151 asn1_pop_tag(&data);
00152 asn1_pop_tag(&data);
00153 asn1_pop_tag(&data);
00154
00155 if (data.has_error) {
00156 DEBUG(2,("Failed to build cldap netlogon at offset %d\n", (int)data.ofs));
00157 asn1_free(&data);
00158 return -1;
00159 }
00160
00161 if (write(sock, data.data, data.length) != (ssize_t)data.length) {
00162 DEBUG(2,("failed to send cldap query (%s)\n", strerror(errno)));
00163 asn1_free(&data);
00164 return -1;
00165 }
00166
00167 asn1_free(&data);
00168
00169 return 0;
00170 }
00171
00172 static SIG_ATOMIC_T gotalarm;
00173
00174
00175
00176
00177
00178 static void gotalarm_sig(void)
00179 {
00180 gotalarm = 1;
00181 }
00182
00183
00184
00185
00186 static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
00187 {
00188 int ret;
00189 ASN1_DATA data;
00190 DATA_BLOB blob = data_blob(NULL, 0);
00191 DATA_BLOB os1 = data_blob(NULL, 0);
00192 DATA_BLOB os2 = data_blob(NULL, 0);
00193 DATA_BLOB os3 = data_blob(NULL, 0);
00194 int i1;
00195
00196 unsigned int al_secs = MAX(3,lp_ldap_timeout()/2);
00197 char *p;
00198
00199 blob = data_blob(NULL, 8192);
00200 if (blob.data == NULL) {
00201 DEBUG(1, ("data_blob failed\n"));
00202 errno = ENOMEM;
00203 return -1;
00204 }
00205
00206
00207 gotalarm = 0;
00208 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
00209 alarm(al_secs);
00210
00211
00212 ret = read(sock, blob.data, blob.length);
00213
00214
00215 CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
00216 alarm(0);
00217
00218 if (ret <= 0) {
00219 DEBUG(1,("no reply received to cldap netlogon\n"));
00220 data_blob_free(&blob);
00221 return -1;
00222 }
00223 blob.length = ret;
00224
00225 asn1_load(&data, blob);
00226 asn1_start_tag(&data, ASN1_SEQUENCE(0));
00227 asn1_read_Integer(&data, &i1);
00228 asn1_start_tag(&data, ASN1_APPLICATION(4));
00229 asn1_read_OctetString(&data, &os1);
00230 asn1_start_tag(&data, ASN1_SEQUENCE(0));
00231 asn1_start_tag(&data, ASN1_SEQUENCE(0));
00232 asn1_read_OctetString(&data, &os2);
00233 asn1_start_tag(&data, ASN1_SET);
00234 asn1_read_OctetString(&data, &os3);
00235 asn1_end_tag(&data);
00236 asn1_end_tag(&data);
00237 asn1_end_tag(&data);
00238 asn1_end_tag(&data);
00239 asn1_end_tag(&data);
00240
00241 if (data.has_error) {
00242 data_blob_free(&blob);
00243 data_blob_free(&os1);
00244 data_blob_free(&os2);
00245 data_blob_free(&os3);
00246 asn1_free(&data);
00247 DEBUG(1,("Failed to parse cldap reply\n"));
00248 return -1;
00249 }
00250
00251 p = (char *)os3.data;
00252
00253 reply->type = IVAL(p, 0); p += 4;
00254 reply->flags = IVAL(p, 0); p += 4;
00255
00256 memcpy(&reply->guid.info, p, UUID_FLAT_SIZE);
00257 p += UUID_FLAT_SIZE;
00258
00259 p += pull_netlogon_string(reply->forest, p, (const char *)os3.data);
00260 p += pull_netlogon_string(reply->domain, p, (const char *)os3.data);
00261 p += pull_netlogon_string(reply->hostname, p, (const char *)os3.data);
00262 p += pull_netlogon_string(reply->netbios_domain, p, (const char *)os3.data);
00263 p += pull_netlogon_string(reply->netbios_hostname, p, (const char *)os3.data);
00264 p += pull_netlogon_string(reply->unk, p, (const char *)os3.data);
00265
00266 if (reply->type == SAMLOGON_AD_R) {
00267 p += pull_netlogon_string(reply->user_name, p, (const char *)os3.data);
00268 } else {
00269 *reply->user_name = 0;
00270 }
00271
00272 p += pull_netlogon_string(reply->server_site_name, p, (const char *)os3.data);
00273 p += pull_netlogon_string(reply->client_site_name, p, (const char *)os3.data);
00274
00275 reply->version = IVAL(p, 0);
00276 reply->lmnt_token = SVAL(p, 4);
00277 reply->lm20_token = SVAL(p, 6);
00278
00279 data_blob_free(&os1);
00280 data_blob_free(&os2);
00281 data_blob_free(&os3);
00282 data_blob_free(&blob);
00283
00284 asn1_free(&data);
00285
00286 return 0;
00287 }
00288
00289
00290
00291
00292
00293 BOOL ads_cldap_netlogon(const char *server, const char *realm, struct cldap_netlogon_reply *reply)
00294 {
00295 int sock;
00296 int ret;
00297
00298 sock = open_udp_socket(server, LDAP_PORT );
00299 if (sock == -1) {
00300 DEBUG(2,("ads_cldap_netlogon: Failed to open udp socket to %s\n",
00301 server));
00302 return False;
00303 }
00304
00305 ret = send_cldap_netlogon(sock, realm, global_myname(), 6);
00306 if (ret != 0) {
00307 close(sock);
00308 return False;
00309 }
00310 ret = recv_cldap_netlogon(sock, reply);
00311 close(sock);
00312
00313 if (ret == -1) {
00314 return False;
00315 }
00316
00317 return True;
00318 }