예제 #1
0
파일: ntlmauth.c 프로젝트: Ales999/sacc-ocs
/* prepares a base64-encode challenge packet to be sent to the client
 * note: domain should be upper_case
 * note: the storage type for the returned value depends on
 *    base64_encode_bin. Currently this means static storage.
 */
const char *
ntlm_make_challenge(char *domain, char *domain_controller,
    char *challenge_nonce, int challenge_nonce_len)
{
    ntlm_challenge ch;
    int pl = 0;
    const char *encoded;
    memset(&ch, 0, sizeof(ntlm_challenge));	/* reset */
    memcpy(ch.signature, "NTLMSSP", 8);		/* set the signature */
    ch.type = WSWAP(NTLM_CHALLENGE);	/* this is a challenge */
    ntlm_add_to_payload(ch.payload, &pl, &ch.target, domain, strlen(domain),
	NTLM_CHALLENGE_HEADER_OFFSET);
    ch.flags = WSWAP(
	REQUEST_NON_NT_SESSION_KEY |
	CHALLENGE_TARGET_IS_DOMAIN |
	NEGOTIATE_ALWAYS_SIGN |
	NEGOTIATE_USE_NTLM |
	NEGOTIATE_USE_LM |
	NEGOTIATE_ASCII |
	0
	);
    ch.context_low = 0;		/* check this out */
    ch.context_high = 0;
    memcpy(ch.challenge, challenge_nonce, challenge_nonce_len);
    encoded = base64_encode_bin((char *) &ch, NTLM_CHALLENGE_HEADER_OFFSET + pl);
    return encoded;
}
예제 #2
0
void
pciconf_1_writew(U32 pci_id, I32 reg_num, U16 val)
{
	
	*GT_PCI_1_CONFIG_ADDR_REG = DWSWAP(pci_id | (reg_num & PCI_ADDR_REG_SZ));
	if ( pci_id & PCI_ADDR_BUSDEV_M)
		*((U16 *)((GT_PCI_1_CONFIG_DATA + 2) - (reg_num & 0x2))) = val;
	else						/* Galileo */
		*((U16 *)(GT_PCI_1_CONFIG_DATA +(reg_num & 0x2))) = WSWAP(val);
		
}
예제 #3
0
U16
pciconf_readw(U32 pci_id, I32 reg_num)
{
	U16	val;
	
	*GT_PCI_CONFIG_ADDR_REG = DWSWAP(pci_id | (reg_num & PCI_ADDR_REG_SZ));
	if ( pci_id & PCI_ADDR_BUSDEV_M)
		val = *((U16 *)((GT_PCI_CONFIG_DATA + 2) - (reg_num & 0x2)));
	else						/* Galileo */
		val = WSWAP(*((U16 *)(GT_PCI_CONFIG_DATA +(reg_num & 0x2))));
	return(val);
		
}
예제 #4
0
파일: ntlmauth.c 프로젝트: Ales999/sacc-ocs
/* Adds something to the payload. The caller must guarrantee that
 * there is enough space in the payload string to accommodate the
 * added value.
 * payload_length and hdr will be modified as a side-effect.
 * base_offset is the payload offset from the packet's beginning, and is
 */
void
ntlm_add_to_payload(char *payload, int *payload_length,
    strhdr * hdr, char *toadd,
    int toadd_length, int base_offset)
{

    int l = (*payload_length);
    memcpy(payload + l, toadd, toadd_length);

    hdr->len = SSWAP(toadd_length);
    hdr->maxlen = SSWAP(toadd_length);
    hdr->offset = WSWAP(l + base_offset);	/* 48 is the base offset of the payload */
    (*payload_length) += toadd_length;
}
예제 #5
0
파일: ntlmauth.c 프로젝트: Ales999/sacc-ocs
/* fetches a string from the authentication packet.
 * The lstring data-part points to inside the packet itself.
 * It's up to the user to memcpy() that if the value needs to
 * be used in any way that requires a tailing \0. (he can check whether the
 * value is there though, in that case lstring.length==-1).
 */
lstring
ntlm_fetch_string(char *packet, int32_t length, strhdr * str)
{
    int16_t l;			/* length */
    int32_t o;			/* offset */
    lstring rv;

    lstring_zero(rv);

    l = SSWAP(str->len);
    o = WSWAP(str->offset);
    /* debug("fetch_string(plength=%d,l=%d,o=%d)\n",length,l,o); */

    if (l < 0 || o <= 0 || l > MAX_FIELD_LENGTH || o + l > length) {
	/* debug("ntlmssp: insane data (l: %d, o: %d)\n", l,o); */
	return rv;
    }
    rv.str = packet + o;
    rv.l = l;

    return rv;
}
예제 #6
0
// ntlm auth header username extraction - also lets connection persist long enough to complete NTLM negotiation
int ntlminstance::identify(Socket& peercon, Socket& proxycon, HTTPHeader &h, std::string &string)
{
	FDTunnel fdt;
	Socket* upstreamcon;
	Socket ntlmcon;
	String url;
	if (transparent) {
		// we are actually sending to a second Squid, which just does NTLM
		ntlmcon.connect(transparent_ip, transparent_port);
		upstreamcon = &ntlmcon;
		url = h.getUrl();
		h.makeTransparent(false);
	} else {
		upstreamcon = &proxycon;
	}
	String at(h.getAuthType());
	if (transparent && (at != "NTLM")) {
		// obey forwarded-for options in what we send out
		std::string clientip;
		if (o.forwarded_for == 1) {
			if (o.use_xforwardedfor == 1) {
				// grab the X-Forwarded-For IP if available
				clientip = h.getXForwardedForIP();
				// otherwise, grab the IP directly from the client connection
				if (clientip.length() == 0)
					clientip = peercon.getPeerIP();
			} else {
				clientip = peercon.getPeerIP();
			}
			h.addXForwardedFor(clientip);  // add squid-like entry
		}
		
		// in transparent mode, we need to make the initial auth required response
		// appear to come from the smoothie itself as an origin server, not as a proxy.
		//
		// accomplish this by redirecting to a URL that results in accessing DG as if it was
		// a webserver, fudging origin-server-style NTLM auth to the client whilst actually
		// performing proper proxy-style auth to the parent proxy, then redirecting the client
		// back to the actual URL.

		if (!url.contains("sgtransntlmdest=")) {
			// user has not yet been redirected
			// get the browser to make a request to the proxy port on the relevant interface,
			// embedding the original URL they were trying to access.
			// unless they're accessing a domain for which authentication is not required,
			// in which case return a no match response straight away.
			if (no_auth_list >= 0)
			{
#ifdef DGDEBUG
				std::cout << "NTLM: Checking noauthdomains list" << std::endl;
#endif
				std::string::size_type start = url.find("://");
				if (start != std::string::npos)
				{
					start += 3;
					std::string domain;
					domain = url.getHostname();
#ifdef DGDEBUG
					std::cout << "NTLM: URL " << url << ", domain " << domain << std::endl;
#endif
					char *i;
					while ((start = domain.find('.')) != std::string::npos)
					{
						i = o.lm.l[no_auth_list]->findInList(domain.c_str());
						if (i != NULL)
						{
#ifdef DGDEBUG
							std::cout << "NTLM: Found domain in noauthdomains list" << std::endl;
#endif
							return DGAUTH_NOMATCH;
						}
						domain.assign(domain.substr(start + 1));
					}
					if (!domain.empty())
					{
						domain = "." + domain;
						i = o.lm.l[no_auth_list]->findInList(domain.c_str());
						if (i != NULL)
						{
#ifdef DGDEBUG
							std::cout << "NTLM: Found domain in noauthdomains list" << std::endl;
#endif
							return DGAUTH_NOMATCH;
						}
					}
				}
			}
			string = "http://";
			string += hostname;
			string += ":";
			string += String(peercon.getPort()).toCharArray();
			string += "/?sgtransntlmdest=";
			string += url.toCharArray();
#ifdef DGDEBUG
			std::cout << "NTLM - redirecting client to " << string << std::endl;
#endif
			return DGAUTH_REDIRECT;
		}

#ifdef DGDEBUG
		std::cout << "NTLM - forging initial auth required from origin server" << std::endl;
#endif
		// obey forwarded-for options in what we send out
		if (o.forwarded_for == 1) {
			std::string clientip;
			if (o.use_xforwardedfor == 1) {
				// grab the X-Forwarded-For IP if available
				clientip = h.getXForwardedForIP();
				// otherwise, grab the IP directly from the client connection
				if (clientip.length() == 0)
					clientip = peercon.getPeerIP();
			} else {
				clientip = peercon.getPeerIP();
			}
			h.addXForwardedFor(clientip);  // add squid-like entry
		}
		// send a variant on the original request (has to be something Squid will route to the outside
		// world, and that it will require NTLM authentication for)
		String domain(url.after("?sgtransntlmdest=").after("://"));
		if (domain.contains("/")) domain = domain.before("/");
		domain = "http://" + domain + "/";
		h.setURL(domain);
		h.makePersistent();
		h.out(&peercon, upstreamcon, __DGHEADER_SENDALL);
		// grab the auth required response and make it look like it's from the origin server
		h.in(upstreamcon, true);
		h.makeTransparent(true);
		h.makePersistent();
		// send it to the client
		h.out(NULL, &peercon, __DGHEADER_SENDALL);
		if (h.contentLength() != -1)
			fdt.tunnel(*upstreamcon, peercon, false, h.contentLength(), true);
		if (h.isPersistent()) {
			// now grab the client's response to the auth request, and carry on as usual.
			h.in(&peercon, true);
			h.makeTransparent(false);
			at = h.getAuthType();
		} else
			return DGAUTH_NOMATCH;
	} else if (transparent && url.contains("?sgtransntlmdest=")) {
		// send a variant on the original request (has to be something Squid will route to the outside
		// world, and that it will require NTLM authentication for)
		String domain(url.after("?sgtransntlmdest=").after("://"));
		if (domain.contains("/")) domain = domain.before("/");
		domain = "http://" + domain + "/";
		h.setURL(domain);
	}

	if (at != "NTLM") {
		// if no auth currently underway, then...
		if (at.length() == 0) {
			// allow the initial request through so the client will get the proxy's initial auth required response.
			// advertise persistent connections so that parent proxy will agree to advertise NTLM support.
#ifdef DGDEBUG
			std::cout << "No auth negotiation currently in progress - making initial request persistent so that proxy will advertise NTLM" << std::endl;
#endif
			h.makePersistent();
		}
		return DGAUTH_NOMATCH;
	}

#ifdef DGDEBUG
	std::cout << "NTLM - sending step 1" << std::endl;
#endif
	if (o.forwarded_for) {
		std::string clientip;
		if (o.use_xforwardedfor) {
			// grab the X-Forwarded-For IP if available
			clientip = h.getXForwardedForIP();
			// otherwise, grab the IP directly from the client connection
			if (clientip.length() == 0)
				clientip = peercon.getPeerIP();
		} else {
			clientip = peercon.getPeerIP();
		}
		h.addXForwardedFor(clientip);  // add squid-like entry
	}
	h.makePersistent();
	h.out(&peercon, upstreamcon, __DGHEADER_SENDALL);
#ifdef DGDEBUG
	std::cout << "NTLM - receiving step 2" << std::endl;
#endif
	h.in(upstreamcon, true);

	if (h.authRequired()) {
#ifdef DGDEBUG
		std::cout << "NTLM - sending step 2" << std::endl;
#endif
		if (transparent)
			h.makeTransparent(true);
		h.out(NULL, &peercon, __DGHEADER_SENDALL);
		if (h.contentLength() != -1)
			fdt.tunnel(*upstreamcon, peercon, false, h.contentLength(), true);
#ifdef DGDEBUG
		std::cout << "NTLM - receiving step 3" << std::endl;
#endif
		h.in(&peercon, true);
		if (transparent) {
			h.makeTransparent(false);
			String domain(url.after("?sgtransntlmdest=").after("://"));
			if (domain.contains("/")) domain = domain.before("/");
			domain = "http://" + domain + "/";
			h.setURL(domain);
		}

#ifdef DGDEBUG
		std::cout << "NTLM - decoding type 3 message" << std::endl;
#endif

		std::string message(h.getAuthData());

		ntlm_authenticate auth;
		ntlm_auth *a = &(auth.a);
		static char username[256]; // fixed size
		static char username2[256];
		char* inptr = username;
		char* outptr = username2;
		size_t l,o;

		// copy the NTLM message into the union's buffer, simultaneously filling in the struct
		if ((message.length() > sizeof(ntlm_auth)) || (message.length() < offsetof(ntlm_auth, payload))) {
			syslog(LOG_ERR, "NTLM - Invalid message of length %zd, message was: %s", message.length(), message.c_str());
#ifdef DGDEBUG
			std::cerr << "NTLM - Invalid message of length " << message.length() << ", message was: " << message << std::endl;
#endif
			return -3;
		}
		memcpy((void *)auth.buf, (const void *)message.c_str(), message.length());

		// verify that the message is indeed a type 3
		if (strcmp("NTLMSSP",a->h.signature) == 0 && WSWAP(a->h.type) == 3) {
			// grab the length & offset of the username within the message
			// cope with the possibility we are a different byte order to Windows
			l = SSWAP(a->user.len);
			o = WSWAP(a->user.offset);

			if ((l > 0) && (o >= 0) && (o + l) <= sizeof(a->payload) && (l <= 254)) {
				// everything is in range
				// note offsets are from start of packet - not the start of the payload area
				memcpy((void *)username, (const void *)&(auth.buf[o]),l);
				username[l] = '\0';
				// check flags - we may need to convert from UTF-16 to something more sensible
				int f = WSWAP(a->flags);
				if (f & WSWAP(0x0001)) {
					iconv_t ic = iconv_open("UTF-8", "UTF-16LE");
					if (ic == (iconv_t)-1) {
						syslog(LOG_ERR, "NTLM - Cannot initialise conversion from UTF-16LE to UTF-8: %s", strerror(errno));
#ifdef DGDEBUG
						std::cerr << "NTLM - Cannot initialise conversion from UTF-16LE to UTF-8: " << strerror(errno) << std::endl;
#endif
						iconv_close(ic);
						return -2;
					}
					size_t l2 = 256;
					local_iconv_adaptor(iconv, ic, &inptr, &l, &outptr, &l2);
					iconv_close(ic);
					username2[256 - l2] = '\0';
#ifdef DGDEBUG
					std::cout << "NTLM - got username (converted from UTF-16LE) " << username2 << std::endl;
#endif
					string = username2;
				} else {
#ifdef DGDEBUG
					std::cout << "NTLM - got username " << username << std::endl;
#endif
					string = username;
				}
				if (!transparent)
					return DGAUTH_OK;
				// if in transparent mode, send a redirect to the client's original requested URL,
				// having sent the final headers to the NTLM-only Squid to do with what it will
				std::string tmp = peercon.getPeerIP();
				h.addXForwardedFor(tmp);
				h.out(&peercon, upstreamcon, __DGHEADER_SENDALL);
				// also, the return code matters in ways it hasn't mattered before:
				// mustn't send a redirect if it is still 407, or we get a redirection loop
				h.in(upstreamcon, true);
				if (h.returnCode() == 407)
				{
					h.makeTransparent(false);
					h.out(NULL, &peercon, __DGHEADER_SENDALL);
					return -10;
				}
				url = url.after("=");
				string = url.toCharArray();
				return DGAUTH_REDIRECT;
			}
		}
		return DGAUTH_NOMATCH;
	} else {
#ifdef DGDEBUG
		std::cout << "NTLM - step 2 was not part of an auth handshake!" << std::endl;
		for (unsigned int i = 0; i < h.header.size(); i++)
			std::cout << h.header[i] << std::endl;
#endif
		syslog(LOG_ERR, "NTLM - step 2 was not part of an auth handshake! (%s)", h.header[0].toCharArray());
		return -1;
	}
}