/* The following definitions come from smbd/reply.c */
-void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size);
void reply_tcon(struct smb_request *req);
void reply_tcon_and_X(struct smb_request *req);
void reply_unknown_new(struct smb_request *req, uint8_t type);
files_struct *fsp);
bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
files_struct *fsp);
+void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size);
/* The following definitions come from smbd/seal.c */
#include "source3/printing/rap_jobid.h"
#include "source3/lib/substitute.h"
-/****************************************************************************
- Return the port number we've bound to on a socket.
-****************************************************************************/
-
-static int get_socket_port(int fd)
-{
- struct samba_sockaddr saddr = {
- .sa_socklen = sizeof(struct sockaddr_storage),
- };
-
- if (fd == -1) {
- return -1;
- }
-
- if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
- int level = (errno == ENOTCONN) ? 2 : 0;
- DEBUG(level, ("getsockname failed. Error was %s\n",
- strerror(errno)));
- return -1;
- }
-
-#if defined(HAVE_IPV6)
- if (saddr.u.sa.sa_family == AF_INET6) {
- return ntohs(saddr.u.in6.sin6_port);
- }
-#endif
- if (saddr.u.sa.sa_family == AF_INET) {
- return ntohs(saddr.u.in.sin_port);
- }
- return -1;
-}
-
-static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
- 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 = NBT_SMB_PORT;
- struct sockaddr_storage retarget_addr;
- struct sockaddr_in *in_addr;
- bool ret = false;
- uint8_t outbuf[10];
-
- if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
- 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';
- if (sscanf(p, "%x", &retarget_type) != 1) {
- goto fail;
- }
- }
-
- ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
- 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 *)(void *)&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(xconn, (char *)outbuf, false, 0, false,
- NULL)) {
- exit_server_cleanly("netbios_session_retarget: srv_send_smb "
- "failed.");
- }
-
- ret = true;
- fail:
- TALLOC_FREE(trim_name);
- return ret;
-}
-
-static void reply_called_name_not_present(char *outbuf)
-{
- smb_setlen(outbuf, 1);
- SCVAL(outbuf, 0, 0x83);
- SCVAL(outbuf, 4, 0x82);
-}
-
-/****************************************************************************
- Reply to a (netbios-level) special message.
-****************************************************************************/
-
-void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
-{
- struct smbd_server_connection *sconn = xconn->client->sconn;
- int msg_type = CVAL(inbuf,0);
- int msg_flags = CVAL(inbuf,1);
- /*
- * We only really use 4 bytes of the outbuf, but for the smb_setlen
- * calculation & friends (srv_send_smb uses that) we need the full smb
- * header.
- */
- char outbuf[smb_size];
-
- memset(outbuf, '\0', sizeof(outbuf));
-
- smb_setlen(outbuf,0);
-
- switch (msg_type) {
- case NBSSrequest: /* session request */
- {
- /* inbuf_size is guarenteed to be at least 4. */
- fstring name1,name2;
- int name_type1, name_type2;
- int name_len1, name_len2;
-
- *name1 = *name2 = 0;
-
- if (xconn->transport.nbt.got_session) {
- exit_server_cleanly("multiple session request not permitted");
- }
-
- SCVAL(outbuf,0,NBSSpositive);
- SCVAL(outbuf,3,0);
-
- /* inbuf_size is guaranteed to be at least 4. */
- name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
- if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
- DEBUG(0,("Invalid name length in session request\n"));
- reply_called_name_not_present(outbuf);
- break;
- }
- name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
- if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
- DEBUG(0,("Invalid name length in session request\n"));
- reply_called_name_not_present(outbuf);
- break;
- }
-
- name_type1 = name_extract((unsigned char *)inbuf,
- inbuf_size,(unsigned int)4,name1);
- name_type2 = name_extract((unsigned char *)inbuf,
- inbuf_size,(unsigned int)(4 + name_len1),name2);
-
- if (name_type1 == -1 || name_type2 == -1) {
- DEBUG(0,("Invalid name type in session request\n"));
- reply_called_name_not_present(outbuf);
- break;
- }
-
- DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
- name1, name_type1, name2, name_type2));
-
- if (netbios_session_retarget(xconn, name1, name_type1)) {
- exit_server_cleanly("retargeted client");
- }
-
- /*
- * Windows NT/2k uses "*SMBSERVER" and XP uses
- * "*SMBSERV" arrggg!!!
- */
- if (strequal(name1, "*SMBSERVER ")
- || strequal(name1, "*SMBSERV ")) {
- char *raddr;
-
- raddr = tsocket_address_inet_addr_string(sconn->remote_address,
- talloc_tos());
- if (raddr == NULL) {
- exit_server_cleanly("could not allocate raddr");
- }
-
- fstrcpy(name1, raddr);
- }
-
- set_local_machine_name(name1, True);
- set_remote_machine_name(name2, True);
-
- if (is_ipaddress(sconn->remote_hostname)) {
- char *p = discard_const_p(char, sconn->remote_hostname);
-
- talloc_free(p);
-
- sconn->remote_hostname = talloc_strdup(sconn,
- get_remote_machine_name());
- if (sconn->remote_hostname == NULL) {
- exit_server_cleanly("could not copy remote name");
- }
- xconn->remote_hostname = sconn->remote_hostname;
- }
-
- DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
- get_local_machine_name(), get_remote_machine_name(),
- name_type2));
-
- if (name_type2 == 'R') {
- /* We are being asked for a pathworks session ---
- no thanks! */
- reply_called_name_not_present(outbuf);
- break;
- }
-
- reload_services(sconn, conn_snum_used, true);
- reopen_logs();
-
- xconn->transport.nbt.got_session = true;
- break;
- }
-
- case 0x89: /* session keepalive request
- (some old clients produce this?) */
- SCVAL(outbuf,0,NBSSkeepalive);
- SCVAL(outbuf,3,0);
- break;
-
- case NBSSpositive: /* positive session response */
- case NBSSnegative: /* negative session response */
- case NBSSretarget: /* retarget session response */
- DEBUG(0,("Unexpected session response\n"));
- break;
-
- case NBSSkeepalive: /* session keepalive */
- default:
- return;
- }
-
- DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
- msg_type, msg_flags));
-
- if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
- exit_server_cleanly("reply_special: srv_send_smb failed.");
- }
-
- if (CVAL(outbuf, 0) != 0x82) {
- exit_server_cleanly("invalid netbios session");
- }
- return;
-}
-
/****************************************************************************
Reply to a tcon.
conn POINTER CAN BE NULL HERE !
return true;
}
+
+/****************************************************************************
+ Return the port number we've bound to on a socket.
+****************************************************************************/
+
+static int get_socket_port(int fd)
+{
+ struct samba_sockaddr saddr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ if (fd == -1) {
+ return -1;
+ }
+
+ if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
+ int level = (errno == ENOTCONN) ? 2 : 0;
+ DEBUG(level, ("getsockname failed. Error was %s\n",
+ strerror(errno)));
+ return -1;
+ }
+
+#if defined(HAVE_IPV6)
+ if (saddr.u.sa.sa_family == AF_INET6) {
+ return ntohs(saddr.u.in6.sin6_port);
+ }
+#endif
+ if (saddr.u.sa.sa_family == AF_INET) {
+ return ntohs(saddr.u.in.sin_port);
+ }
+ return -1;
+}
+
+static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
+ 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 = NBT_SMB_PORT;
+ struct sockaddr_storage retarget_addr;
+ struct sockaddr_in *in_addr;
+ bool ret = false;
+ uint8_t outbuf[10];
+
+ if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
+ 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';
+ if (sscanf(p, "%x", &retarget_type) != 1) {
+ goto fail;
+ }
+ }
+
+ ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
+ 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 *)(void *)&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(xconn, (char *)outbuf, false, 0, false,
+ NULL)) {
+ exit_server_cleanly("netbios_session_retarget: srv_send_smb "
+ "failed.");
+ }
+
+ ret = true;
+ fail:
+ TALLOC_FREE(trim_name);
+ return ret;
+}
+
+static void reply_called_name_not_present(char *outbuf)
+{
+ smb_setlen(outbuf, 1);
+ SCVAL(outbuf, 0, 0x83);
+ SCVAL(outbuf, 4, 0x82);
+}
+
+/****************************************************************************
+ Reply to a (netbios-level) special message.
+****************************************************************************/
+
+void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
+{
+ struct smbd_server_connection *sconn = xconn->client->sconn;
+ int msg_type = CVAL(inbuf,0);
+ int msg_flags = CVAL(inbuf,1);
+ /*
+ * We only really use 4 bytes of the outbuf, but for the smb_setlen
+ * calculation & friends (srv_send_smb uses that) we need the full smb
+ * header.
+ */
+ char outbuf[smb_size];
+
+ memset(outbuf, '\0', sizeof(outbuf));
+
+ smb_setlen(outbuf,0);
+
+ switch (msg_type) {
+ case NBSSrequest: /* session request */
+ {
+ /* inbuf_size is guarenteed to be at least 4. */
+ fstring name1,name2;
+ int name_type1, name_type2;
+ int name_len1, name_len2;
+
+ *name1 = *name2 = 0;
+
+ if (xconn->transport.nbt.got_session) {
+ exit_server_cleanly("multiple session request not permitted");
+ }
+
+ SCVAL(outbuf,0,NBSSpositive);
+ SCVAL(outbuf,3,0);
+
+ /* inbuf_size is guaranteed to be at least 4. */
+ name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
+ if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
+ DEBUG(0,("Invalid name length in session request\n"));
+ reply_called_name_not_present(outbuf);
+ break;
+ }
+ name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
+ if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
+ DEBUG(0,("Invalid name length in session request\n"));
+ reply_called_name_not_present(outbuf);
+ break;
+ }
+
+ name_type1 = name_extract((unsigned char *)inbuf,
+ inbuf_size,(unsigned int)4,name1);
+ name_type2 = name_extract((unsigned char *)inbuf,
+ inbuf_size,(unsigned int)(4 + name_len1),name2);
+
+ if (name_type1 == -1 || name_type2 == -1) {
+ DEBUG(0,("Invalid name type in session request\n"));
+ reply_called_name_not_present(outbuf);
+ break;
+ }
+
+ DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
+ name1, name_type1, name2, name_type2));
+
+ if (netbios_session_retarget(xconn, name1, name_type1)) {
+ exit_server_cleanly("retargeted client");
+ }
+
+ /*
+ * Windows NT/2k uses "*SMBSERVER" and XP uses
+ * "*SMBSERV" arrggg!!!
+ */
+ if (strequal(name1, "*SMBSERVER ")
+ || strequal(name1, "*SMBSERV ")) {
+ char *raddr;
+
+ raddr = tsocket_address_inet_addr_string(sconn->remote_address,
+ talloc_tos());
+ if (raddr == NULL) {
+ exit_server_cleanly("could not allocate raddr");
+ }
+
+ fstrcpy(name1, raddr);
+ }
+
+ set_local_machine_name(name1, True);
+ set_remote_machine_name(name2, True);
+
+ if (is_ipaddress(sconn->remote_hostname)) {
+ char *p = discard_const_p(char, sconn->remote_hostname);
+
+ talloc_free(p);
+
+ sconn->remote_hostname = talloc_strdup(sconn,
+ get_remote_machine_name());
+ if (sconn->remote_hostname == NULL) {
+ exit_server_cleanly("could not copy remote name");
+ }
+ xconn->remote_hostname = sconn->remote_hostname;
+ }
+
+ DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
+ get_local_machine_name(), get_remote_machine_name(),
+ name_type2));
+
+ if (name_type2 == 'R') {
+ /* We are being asked for a pathworks session ---
+ no thanks! */
+ reply_called_name_not_present(outbuf);
+ break;
+ }
+
+ reload_services(sconn, conn_snum_used, true);
+ reopen_logs();
+
+ xconn->transport.nbt.got_session = true;
+ break;
+ }
+
+ case 0x89: /* session keepalive request
+ (some old clients produce this?) */
+ SCVAL(outbuf,0,NBSSkeepalive);
+ SCVAL(outbuf,3,0);
+ break;
+
+ case NBSSpositive: /* positive session response */
+ case NBSSnegative: /* negative session response */
+ case NBSSretarget: /* retarget session response */
+ DEBUG(0,("Unexpected session response\n"));
+ break;
+
+ case NBSSkeepalive: /* session keepalive */
+ default:
+ return;
+ }
+
+ DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
+ msg_type, msg_flags));
+
+ if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
+ exit_server_cleanly("reply_special: srv_send_smb failed.");
+ }
+
+ if (CVAL(outbuf, 0) != 0x82) {
+ exit_server_cleanly("invalid netbios session");
+ }
+ return;
+}