]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
libcli/smb: add struct smb_transports infrastructure
authorStefan Metzmacher <metze@samba.org>
Wed, 2 Apr 2025 17:51:50 +0000 (19:51 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 18 Apr 2025 10:17:29 +0000 (10:17 +0000)
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 <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
libcli/smb/smb_util.h
libcli/smb/util.c

index cd91e42f30a4721ca069c11fc96aff6018b3a2ec..6ec48625f059f5ee2b81f5cae14eeb2a1e8420b0 100644 (file)
@@ -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 */
index 4861c13dd820c3515d304f6f0a9aac7dae7d28f2..20020c897ffde214c3e016b037a604c29179cc22 100644 (file)
@@ -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;
+}