コード例 #1
0
ファイル: smb2_negprot.c プロジェクト: aixoss/samba
enum protocol_types smbd_smb2_protocol_dialect_match(const uint8_t *indyn,
				const int dialect_count,
				uint16_t *dialect)
{
	struct {
		enum protocol_types proto;
		uint16_t dialect;
	} pd[] = {
		{ PROTOCOL_SMB3_11, SMB3_DIALECT_REVISION_311 },
		{ PROTOCOL_SMB3_10, SMB3_DIALECT_REVISION_310 },
		{ PROTOCOL_SMB3_02, SMB3_DIALECT_REVISION_302 },
		{ PROTOCOL_SMB3_00, SMB3_DIALECT_REVISION_300 },
		{ PROTOCOL_SMB2_24, SMB2_DIALECT_REVISION_224 },
		{ PROTOCOL_SMB2_22, SMB2_DIALECT_REVISION_222 },
		{ PROTOCOL_SMB2_10, SMB2_DIALECT_REVISION_210 },
		{ PROTOCOL_SMB2_02, SMB2_DIALECT_REVISION_202 },
	};
	size_t i;

	for (i = 0; i < ARRAY_SIZE(pd); i ++) {
		size_t c = 0;

		if (lp_server_max_protocol() < pd[i].proto) {
			continue;
		}
		if (lp_server_min_protocol() > pd[i].proto) {
			continue;
		}

		for (c = 0; c < dialect_count; c++) {
			*dialect = SVAL(indyn, c*2);
			if (*dialect == pd[i].dialect) {
				return pd[i].proto;
			}
		}
	}

	return PROTOCOL_NONE;
}
コード例 #2
0
void reply_negprot(struct smb_request *req)
{
	int choice= -1;
	int chosen_level = -1;
	int protocol;
	const char *p;
	int arch = ARCH_ALL;
	int num_cliprotos;
	char **cliprotos;
	int i;
	size_t converted_size;
	struct smbd_server_connection *sconn = req->sconn;

	START_PROFILE(SMBnegprot);

	if (sconn->smb1.negprot.done) {
		END_PROFILE(SMBnegprot);
		exit_server_cleanly("multiple negprot's are not permitted");
	}
	sconn->smb1.negprot.done = true;

	if (req->buflen == 0) {
		DEBUG(0, ("negprot got no protocols\n"));
		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
		END_PROFILE(SMBnegprot);
		return;
	}

	if (req->buf[req->buflen-1] != '\0') {
		DEBUG(0, ("negprot protocols not 0-terminated\n"));
		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
		END_PROFILE(SMBnegprot);
		return;
	}

	p = (const char *)req->buf + 1;

	num_cliprotos = 0;
	cliprotos = NULL;

	while (smbreq_bufrem(req, p) > 0) {

		char **tmp;

		tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
					   num_cliprotos+1);
		if (tmp == NULL) {
			DEBUG(0, ("talloc failed\n"));
			TALLOC_FREE(cliprotos);
			reply_nterror(req, NT_STATUS_NO_MEMORY);
			END_PROFILE(SMBnegprot);
			return;
		}

		cliprotos = tmp;

		if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
				       &converted_size)) {
			DEBUG(0, ("pull_ascii_talloc failed\n"));
			TALLOC_FREE(cliprotos);
			reply_nterror(req, NT_STATUS_NO_MEMORY);
			END_PROFILE(SMBnegprot);
			return;
		}

		DEBUG(3, ("Requested protocol [%s]\n",
			  cliprotos[num_cliprotos]));

		num_cliprotos += 1;
		p += strlen(p) + 2;
	}

	for (i=0; i<num_cliprotos; i++) {
		if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
			arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
				  | ARCH_WIN2K );
		else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
			arch &= ( ARCH_WFWG | ARCH_WIN95 );
		else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
			arch &= ( ARCH_WFWG | ARCH_WIN95 );
		else if (strcsequal(cliprotos[i], "NT LM 0.12"))
			arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
				  | ARCH_CIFSFS);
		else if (strcsequal(cliprotos[i], "SMB 2.001"))
			arch = ARCH_VISTA;		
		else if (strcsequal(cliprotos[i], "LANMAN2.1"))
			arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
		else if (strcsequal(cliprotos[i], "LM1.2X002"))
			arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
		else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
			arch &= ARCH_WINNT;
		else if (strcsequal(cliprotos[i], "XENIX CORE"))
			arch &= ( ARCH_WINNT | ARCH_OS2 );
		else if (strcsequal(cliprotos[i], "Samba")) {
			arch = ARCH_SAMBA;
			break;
		} else if (strcsequal(cliprotos[i], "POSIX 2")) {
			arch = ARCH_CIFSFS;
			break;
		}
	}

	/* CIFSFS can send one arch only, NT LM 0.12. */
	if (i == 1 && (arch & ARCH_CIFSFS)) {
		arch = ARCH_CIFSFS;
	}

	switch ( arch ) {
		case ARCH_CIFSFS:
			set_remote_arch(RA_CIFSFS);
			break;
		case ARCH_SAMBA:
			set_remote_arch(RA_SAMBA);
			break;
		case ARCH_WFWG:
			set_remote_arch(RA_WFWG);
			break;
		case ARCH_WIN95:
			set_remote_arch(RA_WIN95);
			break;
		case ARCH_WINNT:
			if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
				set_remote_arch(RA_WIN2K);
			else
				set_remote_arch(RA_WINNT);
			break;
		case ARCH_WIN2K:
			/* Vista may have been set in the negprot so don't 
			   override it here */
			if ( get_remote_arch() != RA_VISTA )
				set_remote_arch(RA_WIN2K);
			break;
		case ARCH_VISTA:
			set_remote_arch(RA_VISTA);
			break;
		case ARCH_OS2:
			set_remote_arch(RA_OS2);
			break;
		default:
			set_remote_arch(RA_UNKNOWN);
		break;
	}

	/* possibly reload - change of architecture */
	reload_services(sconn, conn_snum_used, true);

	/* moved from the netbios session setup code since we don't have that 
	   when the client connects to port 445.  Of course there is a small
	   window where we are listening to messages   -- jerry */

	serverid_register(messaging_server_id(sconn->msg_ctx),
			  FLAG_MSG_GENERAL|FLAG_MSG_SMBD
			  |FLAG_MSG_PRINT_GENERAL);

	/* Check for protocols, most desirable first */
	for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
		i = 0;
		if ((supported_protocols[protocol].protocol_level <= lp_server_max_protocol()) &&
				(supported_protocols[protocol].protocol_level >= lp_server_min_protocol()))
			while (i < num_cliprotos) {
				if (strequal(cliprotos[i],supported_protocols[protocol].proto_name)) {
					choice = i;
					chosen_level = supported_protocols[protocol].protocol_level;
				}
				i++;
			}
		if(choice != -1)
			break;
	}

	if(choice != -1) {
		fstrcpy(remote_proto,supported_protocols[protocol].short_name);
		reload_services(sconn, conn_snum_used, true);
		supported_protocols[protocol].proto_reply_fn(req, choice);
		DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
	} else {
		DEBUG(0,("No protocol supported !\n"));
		reply_outbuf(req, 1, 0);
		SSVAL(req->outbuf, smb_vwv0, choice);
	}

	DEBUG( 5, ( "negprot index=%d\n", choice ) );

	if ((lp_server_signing() == SMB_SIGNING_REQUIRED)
	    && (chosen_level < PROTOCOL_NT1)) {
		exit_server_cleanly("SMB signing is required and "
			"client negotiated a downlevel protocol");
	}

	TALLOC_FREE(cliprotos);

	if (lp_async_smb_echo_handler() && (chosen_level < PROTOCOL_SMB2_02) &&
	    !fork_echo_handler(sconn)) {
		exit_server("Failed to fork echo handler");
	}

	END_PROFILE(SMBnegprot);
	return;
}