selftest: Run krb5.kdc with an account that has a UPN and an SPN
[kai/samba-autobuild/.git] / source3 / nmbd / nmbd_nameregister.c
index d781e0d89f2d7f9e30be7d65c9713061b505eac9..8b078e6859af3f92384c1625d5896b4158184576 100644 (file)
@@ -21,6 +21,7 @@
 */
 
 #include "includes.h"
+#include "nmbd/nmbd.h"
 
 /* forward declarations */
 static void wins_next_registration(struct response_record *rrec);
@@ -40,8 +41,8 @@ static void register_name_response(struct subnet_record *subrec,
         */
 
        struct nmb_packet *nmb = &p->packet.nmb;
-       BOOL bcast = nmb->header.nm_flags.bcast;
-       BOOL success = True;
+       bool bcast = nmb->header.nm_flags.bcast;
+       bool success = True;
        struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
        struct nmb_name *answer_name = &nmb->answers->rr_name;
        struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
@@ -104,6 +105,14 @@ static void register_name_response(struct subnet_record *subrec,
                         subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
                success = False;
        } else {
+               if (!ip_equal_v4(rrec->packet->ip, p->ip)) {
+                       DEBUG(5,("register_name_response: Ignoring WINS server response "
+                               "from IP %s, for name %s. We sent to IP %s\n",
+                               inet_ntoa(p->ip),
+                               nmb_namestr(answer_name),
+                               inet_ntoa(rrec->packet->ip)));
+                       return;
+               }
                /* Unicast - check to see if the response allows us to have the name. */
                if (nmb->header.opcode == NMB_WACK_OPCODE) {
                        /* WINS server is telling us to wait. Pretend we didn't get
@@ -152,10 +161,11 @@ static void register_name_response(struct subnet_record *subrec,
                if( rrec->success_fn)
                        (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
        } else {
+               struct nmb_name qname = *question_name;
                if( rrec->fail_fn)
                        (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
                /* Remove the name. */
-               standard_fail_register( subrec, rrec, question_name);
+               standard_fail_register( subrec, &qname);
        }
 
        /* Ensure we don't retry. */
@@ -248,8 +258,8 @@ static void register_name_timeout_response(struct subnet_record *subrec,
         */
 
        struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
-       BOOL bcast = sent_nmb->header.nm_flags.bcast;
-       BOOL success = False;
+       bool bcast = sent_nmb->header.nm_flags.bcast;
+       bool success = False;
        struct nmb_name *question_name = &sent_nmb->question.question_name;
        uint16 nb_flags = 0;
        int ttl = 0;
@@ -280,10 +290,11 @@ static void register_name_timeout_response(struct subnet_record *subrec,
                if( rrec->success_fn)
                        (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
        } else {
+               struct nmb_name qname = *question_name;
                if( rrec->fail_fn)
                        (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
                /* Remove the name. */
-               standard_fail_register( subrec, rrec, question_name);
+               standard_fail_register( subrec, &qname);
        }
 
        /* Ensure we don't retry. */
@@ -361,7 +372,7 @@ static void wins_next_registration(struct response_record *rrec)
        tag = (const char *)userdata->data;
 
        for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
-               if (ip_equal(last_ip, subrec->myip)) {
+               if (ip_equal_v4(last_ip, subrec->myip)) {
                        subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
                        break;
                }
@@ -471,17 +482,77 @@ void register_name(struct subnet_record *subrec,
 {
        struct nmb_name nmbname;
        nstring nname;
+       size_t converted_size;
 
        errno = 0;
-       push_ascii_nstring(nname, name);
-        if (errno == E2BIG) {
-               unstring tname;
-               pull_ascii_nstring(tname, sizeof(tname), nname);
-               DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n",
-                       name, tname));
-               make_nmb_name(&nmbname, tname, type);
-       } else {
+       converted_size = push_ascii_nstring(nname, name);
+       if (converted_size != (size_t)-1) {
+               /* Success. */
                make_nmb_name(&nmbname, name, type);
+       } else if (errno == E2BIG) {
+               /*
+                * Name converted to CH_DOS is too large.
+                * try to truncate.
+                */
+               char *converted_str_dos = NULL;
+               char *converted_str_unix = NULL;
+               bool ok;
+
+               converted_size = 0;
+
+               ok = convert_string_talloc(talloc_tos(),
+                               CH_UNIX,
+                               CH_DOS,
+                               name,
+                               strlen(name)+1,
+                               &converted_str_dos,
+                               &converted_size);
+               if (!ok) {
+                       DEBUG(0,("register_name: NetBIOS name %s cannot be "
+                               "converted. Failing to register name.\n",
+                               name));
+                       return;
+               }
+
+               /*
+                * As it's now CH_DOS codepage
+                * we truncate by writing '\0' at
+                * MAX_NETBIOSNAME_LEN-1 and then
+                * convert back to CH_UNIX which we
+                * need for the make_nmb_name() call.
+                */
+               if (converted_size >= MAX_NETBIOSNAME_LEN) {
+                       converted_str_dos[MAX_NETBIOSNAME_LEN-1] = '\0';
+               }
+
+               ok = convert_string_talloc(talloc_tos(),
+                               CH_DOS,
+                               CH_UNIX,
+                               converted_str_dos,
+                               strlen(converted_str_dos)+1,
+                               &converted_str_unix,
+                               &converted_size);
+               if (!ok) {
+                       DEBUG(0,("register_name: NetBIOS name %s cannot be "
+                               "converted back to CH_UNIX. "
+                               "Failing to register name.\n",
+                               converted_str_dos));
+                       TALLOC_FREE(converted_str_dos);
+                       return;
+               }
+
+               make_nmb_name(&nmbname, converted_str_unix, type);
+
+               TALLOC_FREE(converted_str_dos);
+               TALLOC_FREE(converted_str_unix);
+       } else {
+               /*
+                * Generic conversion error. Fail to register.
+                */
+               DEBUG(0,("register_name: NetBIOS name %s cannot be "
+                       "converted (%s). Failing to register name.\n",
+                       name, strerror(errno)));
+               return;
        }
 
        /* Always set the NB_ACTIVE flag on the name we are