summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/reply.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 0f2d71eba5..e1364f2462 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -407,6 +407,95 @@ bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
return False;
}
+static bool netbios_session_retarget(const char *name, int name_type)
+{
+ char *trim_name;
+ char *trim_name_type;
+ const char *retarget_parm;
+ char *retarget;
+ char *p;
+ int retarget_type = 0x20;
+ int retarget_port = 139;
+ struct sockaddr_storage retarget_addr;
+ struct sockaddr_in *in_addr;
+ bool ret = false;
+ uint8_t outbuf[10];
+
+ if (get_socket_port(smbd_server_fd()) != 139) {
+ return false;
+ }
+
+ trim_name = talloc_strdup(talloc_tos(), name);
+ if (trim_name == NULL) {
+ goto fail;
+ }
+ trim_char(trim_name, ' ', ' ');
+
+ trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
+ name_type);
+ if (trim_name_type == NULL) {
+ goto fail;
+ }
+
+ retarget_parm = lp_parm_const_string(-1, "netbios retarget",
+ trim_name_type, NULL);
+ if (retarget_parm == NULL) {
+ retarget_parm = lp_parm_const_string(-1, "netbios retarget",
+ trim_name, NULL);
+ }
+ if (retarget_parm == NULL) {
+ goto fail;
+ }
+
+ retarget = talloc_strdup(trim_name, retarget_parm);
+ if (retarget == NULL) {
+ goto fail;
+ }
+
+ DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
+
+ p = strchr(retarget, ':');
+ if (p != NULL) {
+ *p++ = '\0';
+ retarget_port = atoi(p);
+ }
+
+ p = strchr_m(retarget, '#');
+ if (p != NULL) {
+ *p++ = '\0';
+ sscanf(p, "%x", &retarget_type);
+ }
+
+ ret = resolve_name(retarget, &retarget_addr, retarget_type);
+ if (!ret) {
+ DEBUG(10, ("could not resolve %s\n", retarget));
+ goto fail;
+ }
+
+ if (retarget_addr.ss_family != AF_INET) {
+ DEBUG(10, ("Retarget target not an IPv4 addr\n"));
+ goto fail;
+ }
+
+ in_addr = (struct sockaddr_in *)&retarget_addr;
+
+ _smb_setlen(outbuf, 6);
+ SCVAL(outbuf, 0, 0x84);
+ *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
+ *(uint16_t *)(outbuf+8) = htons(retarget_port);
+
+ if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
+ NULL)) {
+ exit_server_cleanly("netbios_session_regarget: srv_send_smb "
+ "failed.");
+ }
+
+ ret = true;
+ fail:
+ TALLOC_FREE(trim_name);
+ return ret;
+}
+
/****************************************************************************
Reply to a (netbios-level) special message.
****************************************************************************/
@@ -450,6 +539,10 @@ void reply_special(char *inbuf)
DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
name1, name_type1, name2, name_type2));
+ if (netbios_session_retarget(name1, name_type1)) {
+ exit_server_cleanly("retargeted client");
+ }
+
set_local_machine_name(name1, True);
set_remote_machine_name(name2, True);