From 43a5fd564ca2efd59b07416ef36c4f7defb9ce53 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 2 Apr 2025 19:51:50 +0200 Subject: [PATCH] libcli/smb: add struct smb_transports infrastructure This will be able to use a structure instead of a string array with int string values for 'smb ports'. We'll soon add support for smb over quic, so we need something better than tcp ports with 139 being special. Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke --- libcli/smb/smb_util.h | 20 +++++++ libcli/smb/util.c | 130 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) diff --git a/libcli/smb/smb_util.h b/libcli/smb/smb_util.h index cd91e42f30a..6ec48625f05 100644 --- a/libcli/smb/smb_util.h +++ b/libcli/smb/smb_util.h @@ -57,4 +57,24 @@ NTSTATUS smb_bytes_pull_str(TALLOC_CTX *mem_ctx, char **_str, bool ucs2, enum smb_signing_setting smb_signing_setting_translate(const char *str); enum smb_encryption_setting smb_encryption_setting_translate(const char *str); +enum smb_transport_type { + SMB_TRANSPORT_TYPE_UNKNOWN = 0, + SMB_TRANSPORT_TYPE_NBT, + SMB_TRANSPORT_TYPE_TCP, +}; + +struct smb_transport { + enum smb_transport_type type; + uint16_t port; +}; + +struct smb_transports { +#define SMB_TRANSPORTS_MAX_TRANSPORTS 10 + uint8_t num_transports; + struct smb_transport transports[SMB_TRANSPORTS_MAX_TRANSPORTS]; +}; + +struct smb_transports smb_transports_parse(const char *param_name, + const char * const *transports); + #endif /* _SMB_UTIL_H */ diff --git a/libcli/smb/util.c b/libcli/smb/util.c index 4861c13dd82..20020c897ff 100644 --- a/libcli/smb/util.c +++ b/libcli/smb/util.c @@ -724,3 +724,133 @@ NTSTATUS smb311_capabilities_check(const struct smb311_capabilities *c, return NT_STATUS_OK; } + +static bool smb_transport_parse(const char *_value, struct smb_transport *_t) +{ + size_t _value_len = strlen(_value); + char value[_value_len+1]; + const char *vparam = NULL; + const char *portstr = NULL; + char *p = NULL; + struct smb_transport t = { + .type = SMB_TRANSPORT_TYPE_UNKNOWN, + }; + bool invalid = false; + + memcpy(value, _value, sizeof(value)); + + p = strchr(value, ':'); + if (p != NULL) { + vparam = p + 1; + p[0] = '\0'; + } + + if (strcmp("tcp", value) == 0) { + t.type = SMB_TRANSPORT_TYPE_TCP; + t.port = 445; + } else if (strcmp("nbt", value) == 0) { + t.type = SMB_TRANSPORT_TYPE_NBT; + t.port = 139; + } else if (vparam != NULL) { + /* + * a port number should not have + * extra parameter! + */ + invalid = true; + } else { + /* + * Could a port number only + */ + portstr = value; + } + + if (!invalid && portstr == NULL) { + portstr = vparam; + } + + if (portstr != NULL) { + char *_end = NULL; + int _port = 0; + _port = strtol(portstr, &_end, 10); + if (*_end != '\0' || _port <= 0 || _port > 65535) { + invalid = true; + } else { + t.port = _port; + } + } + + if (invalid) { + t = (struct smb_transport) { + .type = SMB_TRANSPORT_TYPE_UNKNOWN, + }; + + *_t = t; + return false; + } + + if (t.type == SMB_TRANSPORT_TYPE_UNKNOWN) { + if (t.port == 139) { + t.type = SMB_TRANSPORT_TYPE_NBT; + } else { + t.type = SMB_TRANSPORT_TYPE_TCP; + } + } + + *_t = t; + return true; +} + +struct smb_transports smb_transports_parse(const char *param_name, + const char * const *transports) +{ + struct smb_transports ts = { + .num_transports = 0, + }; + size_t ti; + + for (ti = 0; transports != NULL && transports[ti] != NULL; ti++) { + struct smb_transport t = { + .type = SMB_TRANSPORT_TYPE_UNKNOWN, + }; + bool ignore = false; + size_t ei; + bool ok = false; + + if (ts.num_transports >= SMB_TRANSPORTS_MAX_TRANSPORTS) { + DBG_ERR("WARNING: Ignoring trailing value '%s' for parameter '%s'\n", + transports[ti], param_name); + continue; + } + + ok = smb_transport_parse(transports[ti], &t); + if (!ok) { + DBG_ERR("WARNING: Ignoring invalid value '%s' for parameter '%s'\n", + transports[ti], param_name); + continue; + } + + for (ei = 0; ei < ts.num_transports; ei++) { + if (t.type != ts.transports[ei].type) { + continue; + } + + if (t.port != ts.transports[ei].port) { + continue; + } + + ignore = true; + break; + } + + if (ignore) { + DBG_ERR("WARNING: Ignoring duplicate value '%s' for parameter '%s'\n", + transports[ti], param_name); + continue; + } + + ts.transports[ts.num_transports] = t; + ts.num_transports += 1; + } + + return ts; +} -- 2.47.3