diff options
Diffstat (limited to 'source4/nbt_server/wins')
-rw-r--r-- | source4/nbt_server/wins/winsdb.c | 136 | ||||
-rw-r--r-- | source4/nbt_server/wins/winsserver.c | 18 | ||||
-rw-r--r-- | source4/nbt_server/wins/winswack.c | 5 |
3 files changed, 108 insertions, 51 deletions
diff --git a/source4/nbt_server/wins/winsdb.c b/source4/nbt_server/wins/winsdb.c index 551bc85727..ff3c787eb0 100644 --- a/source4/nbt_server/wins/winsdb.c +++ b/source4/nbt_server/wins/winsdb.c @@ -83,7 +83,7 @@ static struct ldb_dn *winsdb_dn(TALLOC_CTX *mem_ctx, struct nbt_name *name) { struct ldb_dn *dn; - dn = ldb_dn_string_compose(mem_ctx, NULL, "type=%02x", name->type); + dn = ldb_dn_string_compose(mem_ctx, NULL, "type=0x%02X", name->type); if (dn && name->name && *name->name) { dn = ldb_dn_string_compose(mem_ctx, dn, "name=%s", name->name); } @@ -93,15 +93,20 @@ static struct ldb_dn *winsdb_dn(TALLOC_CTX *mem_ctx, struct nbt_name *name) return dn; } -struct nbt_name *winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) +static NTSTATUS winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct nbt_name **_name) { + NTSTATUS status; struct nbt_name *name; uint32_t cur = 0; name = talloc(mem_ctx, struct nbt_name); - if (!name) goto failed; + if (!name) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } if (dn->comp_num > 3) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; goto failed; } @@ -117,26 +122,31 @@ struct nbt_name *winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) cur++; } else { name->name = talloc_strdup(name, ""); - if (!name->name) goto failed; + if (!name->name) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } } if (dn->comp_num > cur && strcasecmp("type", dn->components[cur].name) == 0) { - name->type = strtoul((char *)dn->components[cur].value.data, NULL, 16); + name->type = strtoul((char *)dn->components[cur].value.data, NULL, 0); cur++; } else { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; goto failed; } - return name; + *_name = name; + return NT_STATUS_OK; failed: talloc_free(name); - return NULL; + return status; } /* decode the winsdb_addr("address") attribute: "172.31.1.1" or - "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z" + "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z;" are valid records */ static BOOL winsdb_remove_version(struct wins_server *winssrv, uint64_t version) @@ -247,6 +257,7 @@ const char **winsdb_addr_string_list(TALLOC_CTX *mem_ctx, struct winsdb_addr **a */ static struct winsdb_addr *winsdb_addr_decode(struct winsdb_record *rec, TALLOC_CTX *mem_ctx, struct ldb_val *val) { + NTSTATUS status; struct winsdb_addr *addr; char *address; char *wins_owner; @@ -254,7 +265,10 @@ static struct winsdb_addr *winsdb_addr_decode(struct winsdb_record *rec, TALLOC_ char *p; addr = talloc(mem_ctx, struct winsdb_addr); - if (!addr) return NULL; + if (!addr) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } address = (char *)val->data; @@ -264,52 +278,60 @@ static struct winsdb_addr *winsdb_addr_decode(struct winsdb_record *rec, TALLOC_ addr->address = talloc_steal(addr, val->data); addr->wins_owner = rec->wins_owner; addr->expire_time = rec->expire_time; - return addr; + *_addr = addr; + return NT_STATUS_OK; } *p = '\0';p++; addr->address = talloc_strdup(addr, address); if (!addr->address) { - talloc_free(addr); - return NULL; + status = NT_STATUS_NO_MEMORY; + goto failed; } if (strncmp("winsOwner:", p, 10) != 0) { - /* invalid record */ - talloc_free(addr); - return NULL; + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto failed; } wins_owner = p + 10; p = strchr(wins_owner, ';'); if (!p) { - /* invalid record */ - talloc_free(addr); - return NULL; + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto failed; } *p = '\0';p++; addr->wins_owner = talloc_strdup(addr, wins_owner); if (!addr->wins_owner) { - talloc_free(addr); - return NULL; + status = NT_STATUS_NO_MEMORY; + goto failed; } if (strncmp("expireTime:", p, 11) != 0) { - /* invalid record */ - talloc_free(addr); - return NULL; + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto failed; } expire_time = p + 11; + p = strchr(expire_time, ';'); + if (!p) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto failed; + } + *p = '\0';p++; addr->expire_time = ldap_string_to_time(expire_time); - return addr; + *_addr = addr; + return NT_STATUS_OK; +failed: + talloc_free(addr); + return status; } /* encode the winsdb_addr("address") attribute like this: - "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z" + "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z;" */ static int ldb_msg_add_winsdb_addr(struct ldb_context *ldb, struct ldb_message *msg, const char *attr_name, struct winsdb_addr *addr) @@ -317,7 +339,7 @@ static int ldb_msg_add_winsdb_addr(struct ldb_context *ldb, struct ldb_message * struct ldb_val val; const char *str; - str = talloc_asprintf(msg, "%s;winsOwner:%s;expireTime:%s", + str = talloc_asprintf(msg, "%s;winsOwner:%s;expireTime:%s;", addr->address, addr->wins_owner, ldap_timestring(msg, addr->expire_time)); if (!str) return -1; @@ -435,25 +457,33 @@ const char **winsdb_addr_string_list(TALLOC_CTX *mem_ctx, struct winsdb_addr **a /* load a WINS entry from the database */ -struct winsdb_record *winsdb_load(struct wins_server *winssrv, - struct nbt_name *name, TALLOC_CTX *mem_ctx) +NTSTATUS winsdb_lookup(struct ldb_context *wins_db, + struct nbt_name *name, + TALLOC_CTX *mem_ctx, + struct winsdb_record **_rec) { + NTSTATUS status; struct ldb_message **res = NULL; int ret; struct winsdb_record *rec; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); /* find the record in the WINS database */ - ret = ldb_search(winssrv->wins_db, winsdb_dn(tmp_ctx, name), LDB_SCOPE_BASE, + ret = ldb_search(wins_db, winsdb_dn(tmp_ctx, name), LDB_SCOPE_BASE, NULL, NULL, &res); if (res != NULL) { talloc_steal(tmp_ctx, res); } - if (ret != 1) goto failed; + if (ret == 0) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto failed; + } else if (ret != 1) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto failed; + } - rec = winsdb_record(res[0], tmp_ctx); - if (rec == NULL) goto failed; - rec->name = name; + status = winsdb_record(res[0], name, tmp_ctx, &rec); + if (!NT_STATUS_IS_OK(status)) goto failed; /* see if it has already expired */ if (rec->state == WINS_REC_ACTIVE && @@ -465,21 +495,31 @@ struct winsdb_record *winsdb_load(struct wins_server *winssrv, talloc_steal(mem_ctx, rec); talloc_free(tmp_ctx); - return rec; + *_rec = rec; + return NT_STATUS_OK; failed: talloc_free(tmp_ctx); - return NULL; + return status; } -struct winsdb_record *winsdb_record(struct ldb_message *msg, TALLOC_CTX *mem_ctx) +NTSTATUS winsdb_record(struct ldb_message *msg, struct nbt_name *name, TALLOC_CTX *mem_ctx, struct winsdb_record **_rec) { + NTSTATUS status; struct winsdb_record *rec; struct ldb_message_element *el; uint32_t i; rec = talloc(mem_ctx, struct winsdb_record); - if (rec == NULL) goto failed; + if (rec == NULL) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } + + if (!name) { + status = winsdb_nbt_name(rec, msg->dn, &name); + if (!NT_STATUS_IS_OK(status)) goto failed; + } /* parse it into a more convenient winsdb_record structure */ rec->name = name; @@ -494,21 +534,31 @@ struct winsdb_record *winsdb_record(struct ldb_message *msg, TALLOC_CTX *mem_ctx if (!rec->wins_owner) rec->wins_owner = WINSDB_OWNER_LOCAL; el = ldb_msg_find_element(msg, "address"); - if (el == NULL) goto failed; + if (el == NULL) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto failed; + } rec->addresses = talloc_array(rec, struct winsdb_addr *, el->num_values+1); - if (rec->addresses == NULL) goto failed; + if (rec->addresses == NULL) { + status = NT_STATUS_NO_MEMORY; + goto failed; + } for (i=0;i<el->num_values;i++) { - rec->addresses[i] = winsdb_addr_decode(rec, rec->addresses, &el->values[i]); - if (rec->addresses[i] == NULL) goto failed; + status = winsdb_addr_decode(rec, &el->values[i], rec->addresses, &rec->addresses[i]); + if (!NT_STATUS_IS_OK(status)) goto failed; } rec->addresses[i] = NULL; - return rec; + *_rec = rec; + return NT_STATUS_OK; failed: + if (NT_STATUS_EQUAL(NT_STATUS_INTERNAL_DB_CORRUPTION, status)) { + DEBUG(1,("winsdb_record: corrupted record: %s\n", ldb_dn_linearize(rec, msg->dn))); + } talloc_free(rec); - return NULL; + return status; } /* diff --git a/source4/nbt_server/wins/winsserver.c b/source4/nbt_server/wins/winsserver.c index 37b59cdc7f..d5043caa29 100644 --- a/source4/nbt_server/wins/winsserver.c +++ b/source4/nbt_server/wins/winsserver.c @@ -110,6 +110,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, const struct nbt_peer_socket *src) { + NTSTATUS status; struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; @@ -125,10 +126,13 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock, goto done; } - rec = winsdb_load(winssrv, name, packet); - if (rec == NULL) { + status = winsdb_lookup(winssrv->wins_db, name, packet, &rec); + if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) { rcode = wins_register_new(nbtsock, packet, src); goto done; + } else if (!NT_STATUS_IS_OK(status)) { + rcode = NBT_RCODE_SVR; + goto done; } else if (rec->state != WINS_REC_ACTIVE) { winsdb_delete(winssrv, rec); rcode = wins_register_new(nbtsock, packet, src); @@ -182,6 +186,7 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, const struct nbt_peer_socket *src) { + NTSTATUS status; struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; @@ -189,8 +194,8 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock, struct winsdb_record *rec; const char **addresses; - rec = winsdb_load(winssrv, name, packet); - if (rec == NULL || rec->state != WINS_REC_ACTIVE) { + status = winsdb_lookup(winssrv->wins_db, name, packet, &rec); + if (!NT_STATUS_IS_OK(status) || rec->state != WINS_REC_ACTIVE) { nbtd_negative_name_query_reply(nbtsock, packet, src); return; } @@ -212,14 +217,15 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, const struct nbt_peer_socket *src) { + NTSTATUS status; struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; struct nbt_name *name = &packet->questions[0].name; struct winsdb_record *rec; - rec = winsdb_load(winssrv, name, packet); - if (rec == NULL || + status = winsdb_lookup(winssrv->wins_db, name, packet, &rec); + if (!NT_STATUS_IS_OK(status) || rec->state != WINS_REC_ACTIVE || IS_GROUP_NAME(name, rec->nb_flags)) { goto done; diff --git a/source4/nbt_server/wins/winswack.c b/source4/nbt_server/wins/winswack.c index defa3ad09a..64336992f6 100644 --- a/source4/nbt_server/wins/winswack.c +++ b/source4/nbt_server/wins/winswack.c @@ -54,12 +54,13 @@ static void wins_wack_deny(struct wack_state *state) */ static void wins_wack_allow(struct wack_state *state) { + NTSTATUS status; uint32_t ttl; time_t now = time(NULL); struct winsdb_record *rec = state->rec, *rec2; - rec2 = winsdb_load(state->winssrv, rec->name, state); - if (rec2 == NULL || rec2->version != rec->version) { + status = winsdb_lookup(state->winssrv->wins_db, rec->name, state, &rec2); + if (!NT_STATUS_IS_OK(status) || rec2->version != rec->version) { DEBUG(1,("WINS: record %s changed during WACK - failing registration\n", nbt_name_string(state, rec->name))); wins_wack_deny(state); |