1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

libcli:nbt make the lmhosts parsing code and dependicies common

This starts the process to have Samba4 use lmhosts.

Andrew Bartlett
This commit is contained in:
Andrew Bartlett 2009-09-15 07:42:54 -07:00
parent f07e77e13f
commit 668470c992
10 changed files with 346 additions and 298 deletions

View File

@ -21,7 +21,7 @@
#ifndef _SAMBA_UTIL_H_
#define _SAMBA_UTIL_H_
#include <netinet/in.h>
#include "system/network.h"
#if _SAMBA_BUILD_ == 4
#include "../lib/util/charset/charset.h"
@ -842,4 +842,24 @@ bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid,
bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
gid_t **gids, size_t *num_gids);
/* The following definitions come from lib/util/util_net.c */
void zero_sockaddr(struct sockaddr_storage *pss);
bool interpret_string_addr_internal(struct addrinfo **ppres,
const char *str, int flags);
bool interpret_string_addr(struct sockaddr_storage *pss,
const char *str,
int flags);
/*******************************************************************
Map a text hostname or IP address (IPv4 or IPv6) into a
struct sockaddr_storage. Version that prefers IPv4.
******************************************************************/
bool interpret_string_addr_prefer_ipv4(struct sockaddr_storage *pss,
const char *str,
int flags);
#endif /* _SAMBA_UTIL_H_ */

View File

@ -3,10 +3,11 @@
Samba utility functions
Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Jeremy Allison 2001-2007
Copyright (C) Jeremy Allison 1992-2007
Copyright (C) Simo Sorce 2001
Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003.
Copyright (C) James J Myers 2003
Copyright (C) Tim Potter 2000-2001
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -28,6 +29,17 @@
#include "system/filesys.h"
#undef strcasecmp
/*******************************************************************
Set an address to INADDR_ANY.
******************************************************************/
void zero_sockaddr(struct sockaddr_storage *pss)
{
memset(pss, '\0', sizeof(*pss));
/* Ensure we're at least a valid sockaddr-storage. */
pss->ss_family = AF_INET;
}
/**
* Wrap getaddrinfo...
*/
@ -59,6 +71,110 @@ bool interpret_string_addr_internal(struct addrinfo **ppres,
return true;
}
/*******************************************************************
Map a text hostname or IP address (IPv4 or IPv6) into a
struct sockaddr_storage. Takes a flag which allows it to
prefer an IPv4 address (needed for DC's).
******************************************************************/
static bool interpret_string_addr_pref(struct sockaddr_storage *pss,
const char *str,
int flags,
bool prefer_ipv4)
{
struct addrinfo *res = NULL;
#if defined(HAVE_IPV6)
char addr[INET6_ADDRSTRLEN];
unsigned int scope_id = 0;
if (strchr_m(str, ':')) {
char *p = strchr_m(str, '%');
/*
* Cope with link-local.
* This is IP:v6:addr%ifname.
*/
if (p && (p > str) && ((scope_id = if_nametoindex(p+1)) != 0)) {
strlcpy(addr, str,
MIN(PTR_DIFF(p,str)+1,
sizeof(addr)));
str = addr;
}
}
#endif
zero_sockaddr(pss);
if (!interpret_string_addr_internal(&res, str, flags|AI_ADDRCONFIG)) {
return false;
}
if (!res) {
return false;
}
if (prefer_ipv4) {
struct addrinfo *p;
for (p = res; p; p = p->ai_next) {
if (p->ai_family == AF_INET) {
memcpy(pss, p->ai_addr, p->ai_addrlen);
break;
}
}
if (p == NULL) {
/* Copy the first sockaddr. */
memcpy(pss, res->ai_addr, res->ai_addrlen);
}
} else {
/* Copy the first sockaddr. */
memcpy(pss, res->ai_addr, res->ai_addrlen);
}
#if defined(HAVE_IPV6)
if (pss->ss_family == AF_INET6 && scope_id) {
struct sockaddr_in6 *ps6 = (struct sockaddr_in6 *)pss;
if (IN6_IS_ADDR_LINKLOCAL(&ps6->sin6_addr) &&
ps6->sin6_scope_id == 0) {
ps6->sin6_scope_id = scope_id;
}
}
#endif
freeaddrinfo(res);
return true;
}
/*******************************************************************
Map a text hostname or IP address (IPv4 or IPv6) into a
struct sockaddr_storage. Address agnostic version.
******************************************************************/
bool interpret_string_addr(struct sockaddr_storage *pss,
const char *str,
int flags)
{
return interpret_string_addr_pref(pss,
str,
flags,
false);
}
/*******************************************************************
Map a text hostname or IP address (IPv4 or IPv6) into a
struct sockaddr_storage. Version that prefers IPv4.
******************************************************************/
bool interpret_string_addr_prefer_ipv4(struct sockaddr_storage *pss,
const char *str,
int flags)
{
return interpret_string_addr_pref(pss,
str,
flags,
true);
}
/**
* Interpret an internet address or name into an IP address in 4 byte form.
* RETURNS IN NETWORK BYTE ORDER (big endian).

50
libcli/nbt/config.mk Normal file
View File

@ -0,0 +1,50 @@
[SUBSYSTEM::NDR_NBT_BUF]
NDR_NBT_BUF_OBJ_FILES = $(libclinbtsrcdir)/nbtname.o
$(eval $(call proto_header_template,$(libclinbtsrcdir)/nbtname.h,$(NDR_NBT_BUF_OBJ_FILES:.o=.c)))
[SUBSYSTEM::LIBCLI_NBT]
PUBLIC_DEPENDENCIES = LIBNDR NDR_NBT LIBCLI_COMPOSITE LIBEVENTS \
NDR_SECURITY samba_socket LIBSAMBA-UTIL
LIBCLI_NBT_OBJ_FILES = $(addprefix $(libclinbtsrcdir)/, \
lmhosts.o \
nbtsocket.o \
namequery.o \
nameregister.o \
namerefresh.o \
namerelease.o)
[BINARY::nmblookup]
INSTALLDIR = BINDIR
PRIVATE_DEPENDENCIES = \
LIBSAMBA-HOSTCONFIG \
LIBSAMBA-UTIL \
LIBCLI_NBT \
LIBPOPT \
POPT_SAMBA \
LIBNETIF \
LIBCLI_RESOLVE
nmblookup_OBJ_FILES = $(libclinbtsrcdir)/tools/nmblookup.o
MANPAGES += $(libclinbtsrcdir)/man/nmblookup.1
[SUBSYSTEM::LIBCLI_NDR_NETLOGON]
PUBLIC_DEPENDENCIES = LIBNDR \
NDR_SECURITY
LIBCLI_NDR_NETLOGON_OBJ_FILES = $(addprefix $(libclinbtsrcdir)/../, ndr_netlogon.o)
[SUBSYSTEM::LIBCLI_NETLOGON]
PUBLIC_DEPENDENCIES = LIBSAMBA-UTIL LIBCLI_NDR_NETLOGON
LIBCLI_NETLOGON_OBJ_FILES = $(addprefix $(libclinbtsrcdir)/, \
../netlogon.o)
[PYTHON::python_netbios]
LIBRARY_REALNAME = samba/netbios.$(SHLIBEXT)
PUBLIC_DEPENDENCIES = LIBCLI_NBT DYNCONFIG LIBSAMBA-HOSTCONFIG
python_netbios_OBJ_FILES = $(libclinbtsrcdir)/pynbt.o

156
libcli/nbt/lmhosts.c Normal file
View File

@ -0,0 +1,156 @@
/*
Unix SMB/CIFS implementation.
manipulate nbt name structures
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Jeremy Allison 2007
Copyright (C) Andrew Bartlett 2009.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "lib/util/xfile.h"
#include "system/filesys.h"
#include "system/network.h"
/********************************************************
Start parsing the lmhosts file.
*********************************************************/
XFILE *startlmhosts(const char *fname)
{
XFILE *fp = x_fopen(fname,O_RDONLY, 0);
if (!fp) {
DEBUG(4,("startlmhosts: Can't open lmhosts file %s. "
"Error was %s\n",
fname, strerror(errno)));
return NULL;
}
return fp;
}
/********************************************************
Parse the next line in the lmhosts file.
*********************************************************/
bool getlmhostsent(TALLOC_CTX *ctx, XFILE *fp, char **pp_name, int *name_type,
struct sockaddr_storage *pss)
{
char line[1024];
*pp_name = NULL;
while(!x_feof(fp) && !x_ferror(fp)) {
char *ip = NULL;
char *flags = NULL;
char *extra = NULL;
char *name = NULL;
const char *ptr;
char *ptr1 = NULL;
int count = 0;
*name_type = -1;
if (!fgets_slash(line,sizeof(line),fp)) {
continue;
}
if (*line == '#') {
continue;
}
ptr = line;
if (next_token_talloc(ctx, &ptr, &ip, NULL))
++count;
if (next_token_talloc(ctx, &ptr, &name, NULL))
++count;
if (next_token_talloc(ctx, &ptr, &flags, NULL))
++count;
if (next_token_talloc(ctx, &ptr, &extra, NULL))
++count;
if (count <= 0)
continue;
if (count > 0 && count < 2) {
DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",
line));
continue;
}
if (count >= 4) {
DEBUG(0,("getlmhostsent: too many columns "
"in lmhosts file (obsolete syntax)\n"));
continue;
}
if (!flags) {
flags = talloc_strdup(ctx, "");
if (!flags) {
continue;
}
}
DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n",
ip, name, flags));
if (strchr_m(flags,'G') || strchr_m(flags,'S')) {
DEBUG(0,("getlmhostsent: group flag "
"in lmhosts ignored (obsolete)\n"));
continue;
}
if (!interpret_string_addr(pss, ip, AI_NUMERICHOST)) {
DEBUG(0,("getlmhostsent: invalid address "
"%s.\n", ip));
}
/* Extra feature. If the name ends in '#XX',
* where XX is a hex number, then only add that name type. */
if((ptr1 = strchr_m(name, '#')) != NULL) {
char *endptr;
ptr1++;
*name_type = (int)strtol(ptr1, &endptr, 16);
if(!*ptr1 || (endptr == ptr1)) {
DEBUG(0,("getlmhostsent: invalid name "
"%s containing '#'.\n", name));
continue;
}
*(--ptr1) = '\0'; /* Truncate at the '#' */
}
*pp_name = talloc_strdup(ctx, name);
if (!*pp_name) {
return false;
}
return true;
}
return false;
}
/********************************************************
Finish parsing the lmhosts file.
*********************************************************/
void endlmhosts(XFILE *fp)
{
x_fclose(fp);
}

View File

@ -455,7 +455,7 @@ LIBNBT_OBJ = ../libcli/nbt/nbtname.o \
../librpc/ndr/ndr_svcctl.o
LIBNMB_OBJ = libsmb/unexpected.o libsmb/namecache.o libsmb/nmblib.o \
libsmb/namequery.o libsmb/conncache.o libads/dns.o
libsmb/namequery.o ../libcli/nbt/lmhosts.o libsmb/conncache.o libads/dns.o
NTERR_OBJ = libsmb/nterr.o libsmb/smberr.o
DOSERR_OBJ = ../libcli/util/doserr.o

View File

@ -1342,20 +1342,11 @@ NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx,
/* The following definitions come from lib/util_sock.c */
bool interpret_string_addr_internal(struct addrinfo **ppres,
const char *str, int flags);
bool is_broadcast_addr(const struct sockaddr *pss);
bool interpret_string_addr(struct sockaddr_storage *pss,
const char *str,
int flags);
bool interpret_string_addr_prefer_ipv4(struct sockaddr_storage *pss,
const char *str,
int flags);
bool is_loopback_ip_v4(struct in_addr ip);
bool is_loopback_addr(const struct sockaddr *pss);
bool is_zero_addr(const struct sockaddr *pss);
void zero_ip_v4(struct in_addr *ip);
void zero_sockaddr(struct sockaddr_storage *pss);
void in_addr_to_sockaddr_storage(struct sockaddr_storage *ss,
struct in_addr ip);
bool same_net(const struct sockaddr *ip1,

View File

@ -21,121 +21,6 @@
#include "includes.h"
/*******************************************************************
Map a text hostname or IP address (IPv4 or IPv6) into a
struct sockaddr_storage. Takes a flag which allows it to
prefer an IPv4 address (needed for DC's).
******************************************************************/
static bool interpret_string_addr_pref(struct sockaddr_storage *pss,
const char *str,
int flags,
bool prefer_ipv4)
{
struct addrinfo *res = NULL;
#if defined(HAVE_IPV6)
char addr[INET6_ADDRSTRLEN];
unsigned int scope_id = 0;
if (strchr_m(str, ':')) {
char *p = strchr_m(str, '%');
/*
* Cope with link-local.
* This is IP:v6:addr%ifname.
*/
if (p && (p > str) && ((scope_id = if_nametoindex(p+1)) != 0)) {
strlcpy(addr, str,
MIN(PTR_DIFF(p,str)+1,
sizeof(addr)));
str = addr;
}
}
#endif
zero_sockaddr(pss);
if (!interpret_string_addr_internal(&res, str, flags|AI_ADDRCONFIG)) {
return false;
}
if (!res) {
return false;
}
if (prefer_ipv4) {
struct addrinfo *p;
for (p = res; p; p = p->ai_next) {
if (p->ai_family == AF_INET) {
memcpy(pss, p->ai_addr, p->ai_addrlen);
break;
}
}
if (p == NULL) {
/* Copy the first sockaddr. */
memcpy(pss, res->ai_addr, res->ai_addrlen);
}
} else {
/* Copy the first sockaddr. */
memcpy(pss, res->ai_addr, res->ai_addrlen);
}
#if defined(HAVE_IPV6)
if (pss->ss_family == AF_INET6 && scope_id) {
struct sockaddr_in6 *ps6 = (struct sockaddr_in6 *)pss;
if (IN6_IS_ADDR_LINKLOCAL(&ps6->sin6_addr) &&
ps6->sin6_scope_id == 0) {
ps6->sin6_scope_id = scope_id;
}
}
#endif
freeaddrinfo(res);
return true;
}
/*******************************************************************
Map a text hostname or IP address (IPv4 or IPv6) into a
struct sockaddr_storage. Address agnostic version.
******************************************************************/
bool interpret_string_addr(struct sockaddr_storage *pss,
const char *str,
int flags)
{
return interpret_string_addr_pref(pss,
str,
flags,
false);
}
/*******************************************************************
Map a text hostname or IP address (IPv4 or IPv6) into a
struct sockaddr_storage. Version that prefers IPv4.
******************************************************************/
bool interpret_string_addr_prefer_ipv4(struct sockaddr_storage *pss,
const char *str,
int flags)
{
return interpret_string_addr_pref(pss,
str,
flags,
true);
}
/*******************************************************************
Set an address to INADDR_ANY.
******************************************************************/
void zero_sockaddr(struct sockaddr_storage *pss)
{
memset(pss, '\0', sizeof(*pss));
/* Ensure we're at least a valid sockaddr-storage. */
pss->ss_family = AF_INET;
}
/****************************************************************************
Get a port number in host byte order from a sockaddr_storage.
****************************************************************************/

View File

@ -846,134 +846,6 @@ struct sockaddr_storage *name_query(int fd,
return ss_list;
}
/********************************************************
Start parsing the lmhosts file.
*********************************************************/
XFILE *startlmhosts(const char *fname)
{
XFILE *fp = x_fopen(fname,O_RDONLY, 0);
if (!fp) {
DEBUG(4,("startlmhosts: Can't open lmhosts file %s. "
"Error was %s\n",
fname, strerror(errno)));
return NULL;
}
return fp;
}
/********************************************************
Parse the next line in the lmhosts file.
*********************************************************/
bool getlmhostsent(TALLOC_CTX *ctx, XFILE *fp, char **pp_name, int *name_type,
struct sockaddr_storage *pss)
{
char line[1024];
*pp_name = NULL;
while(!x_feof(fp) && !x_ferror(fp)) {
char *ip = NULL;
char *flags = NULL;
char *extra = NULL;
char *name = NULL;
const char *ptr;
char *ptr1 = NULL;
int count = 0;
*name_type = -1;
if (!fgets_slash(line,sizeof(line),fp)) {
continue;
}
if (*line == '#') {
continue;
}
ptr = line;
if (next_token_talloc(ctx, &ptr, &ip, NULL))
++count;
if (next_token_talloc(ctx, &ptr, &name, NULL))
++count;
if (next_token_talloc(ctx, &ptr, &flags, NULL))
++count;
if (next_token_talloc(ctx, &ptr, &extra, NULL))
++count;
if (count <= 0)
continue;
if (count > 0 && count < 2) {
DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",
line));
continue;
}
if (count >= 4) {
DEBUG(0,("getlmhostsent: too many columns "
"in lmhosts file (obsolete syntax)\n"));
continue;
}
if (!flags) {
flags = talloc_strdup(ctx, "");
if (!flags) {
continue;
}
}
DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n",
ip, name, flags));
if (strchr_m(flags,'G') || strchr_m(flags,'S')) {
DEBUG(0,("getlmhostsent: group flag "
"in lmhosts ignored (obsolete)\n"));
continue;
}
if (!interpret_string_addr(pss, ip, AI_NUMERICHOST)) {
DEBUG(0,("getlmhostsent: invalid address "
"%s.\n", ip));
}
/* Extra feature. If the name ends in '#XX',
* where XX is a hex number, then only add that name type. */
if((ptr1 = strchr_m(name, '#')) != NULL) {
char *endptr;
ptr1++;
*name_type = (int)strtol(ptr1, &endptr, 16);
if(!*ptr1 || (endptr == ptr1)) {
DEBUG(0,("getlmhostsent: invalid name "
"%s containing '#'.\n", name));
continue;
}
*(--ptr1) = '\0'; /* Truncate at the '#' */
}
*pp_name = talloc_strdup(ctx, name);
if (!*pp_name) {
return false;
}
return true;
}
return false;
}
/********************************************************
Finish parsing the lmhosts file.
*********************************************************/
void endlmhosts(XFILE *fp)
{
x_fclose(fp);
}
/********************************************************
convert an array if struct sockaddr_storage to struct ip_service
return false on failure. Port is set to PORT_NONE;

View File

@ -37,49 +37,6 @@ LIBCLI_SMB_COMPOSITE_OBJ_FILES = $(addprefix $(libclisrcdir)/smb_composite/, \
$(eval $(call proto_header_template,$(libclisrcdir)/smb_composite/proto.h,$(LIBCLI_SMB_COMPOSITE_OBJ_FILES:.o=.c)))
[SUBSYSTEM::NDR_NBT_BUF]
NDR_NBT_BUF_OBJ_FILES = $(libclinbtsrcdir)/nbtname.o
$(eval $(call proto_header_template,$(libclinbtsrcdir)/nbtname.h,$(NDR_NBT_BUF_OBJ_FILES:.o=.c)))
[SUBSYSTEM::LIBCLI_NBT]
PUBLIC_DEPENDENCIES = LIBNDR NDR_NBT LIBCLI_COMPOSITE LIBEVENTS \
NDR_SECURITY samba_socket LIBSAMBA-UTIL
LIBCLI_NBT_OBJ_FILES = $(addprefix $(libclinbtsrcdir)/, \
nbtsocket.o \
namequery.o \
nameregister.o \
namerefresh.o \
namerelease.o)
[BINARY::nmblookup]
INSTALLDIR = BINDIR
PRIVATE_DEPENDENCIES = \
LIBSAMBA-HOSTCONFIG \
LIBSAMBA-UTIL \
LIBCLI_NBT \
LIBPOPT \
POPT_SAMBA \
LIBNETIF \
LIBCLI_RESOLVE
nmblookup_OBJ_FILES = $(libclinbtsrcdir)/tools/nmblookup.o
MANPAGES += $(libclinbtsrcdir)/man/nmblookup.1
[SUBSYSTEM::LIBCLI_NDR_NETLOGON]
PUBLIC_DEPENDENCIES = LIBNDR \
NDR_SECURITY
LIBCLI_NDR_NETLOGON_OBJ_FILES = $(addprefix $(libclinbtsrcdir)/../, ndr_netlogon.o)
[SUBSYSTEM::LIBCLI_NETLOGON]
PUBLIC_DEPENDENCIES = LIBSAMBA-UTIL LIBCLI_NDR_NETLOGON
LIBCLI_NETLOGON_OBJ_FILES = $(addprefix $(libclinbtsrcdir)/, \
../netlogon.o)
[PYTHON::python_netbios]
LIBRARY_REALNAME = samba/netbios.$(SHLIBEXT)
PUBLIC_DEPENDENCIES = LIBCLI_NBT DYNCONFIG LIBSAMBA-HOSTCONFIG

View File

@ -56,6 +56,7 @@ mkinclude ../lib/smbconf/config.mk
mkinclude ../lib/async_req/config.mk
mkinclude ../libcli/security/config.mk
mkinclude ../libcli/ldap/config.mk
mkinclude ../libcli/nbt/config.mk
mkinclude ../libcli/auth/config.mk
mkinclude ../libcli/drsuapi/config.mk
mkinclude ../libcli/samsync/config.mk