예제 #1
0
파일: httpauth.c 프로젝트: maojxsir/upnp
/*---------------------------------------------------------------------------*/
HTTP_INT32 _HTTP_RealmPrintAuthorization (
		HTTPAuthenticationRealm *realm,
		const HTTP_CHAR* method,
		const HTTP_CHAR* path,
		HTTP_INT32 (*writeFn) (
				void* requestStream,
				const HTTP_CHAR* data,
				HTTP_INT32 len
			),
		void* requestStream
	)
{
	switch (realm->scheme)
	{
		case HTTP_AUTHENTICATION_BASIC:
			if (realm->userName[0])
			{
				HTTP_INT32 len = 0;
				char auth[HTTP_CFG_MAX_USERNAME_LEN + HTTP_CFG_MAX_PASSWORD_LEN];
				char encoded[((HTTP_CFG_MAX_USERNAME_LEN + HTTP_CFG_MAX_PASSWORD_LEN) * 4 + 2) /3];

				len =  sizeof(HTTP_CLIENT_BASIC_STR) / sizeof(HTTP_CHAR) - sizeof(HTTP_CHAR);
				writeFn(requestStream, HTTP_CLIENT_BASIC_STR, len);
				writeFn(requestStream, " ", 1);

				tc_strcpy(auth, realm->userName);
				tc_strcat(auth, ":");
				tc_strcat(auth, realm->password);

				len = _HTTP_Base64Encode(encoded, (HTTP_UINT8*) auth, (HTTP_INT32) tc_strlen(auth));

				writeFn(requestStream, encoded, len);

				return (len);
			}
			break;

		case HTTP_AUTHENTICATION_DIGEST:
			if (realm->userName[0])
			{
				HTTP_INT32 len = 0;
				HTTP_MD5_CTX md5Ctx;
				HTTP_CHAR hashA1[32];
				HTTP_CHAR hashA2[32];
				HTTP_CHAR finalHash[33];

				/* according to RFC 2617,
				      credentials = "Digest" digest-response

				   where
				      digest-response = "username=\"" + <user-name> +
					                    "\", realm=\"" + <realm-name> +
										"\", nonce=\"" + <server-nonce> +
										"\", uri=\"" + <path> +
										"\", response=\"" +
										   (qop == auth || qop == auth-int)?
										      KD(H(A1), <nonce> + ":" + <nonce-count> + ":" + <cnonce> + ":" + <qop> + ":" + H(A2)) :
											  KD(H(A1), <nonce> + ":" + H(A2))

				      A1 = <user-name> + ":" + <realm-name> + ":" + <password>

					  A2 = <method (GET,POST,etc)> + ":" + <path>

					  H(X) = MD5(X), as a 32-character HEX string

					  KD(I,J) = H(I + ":" + J);
				*/

				len = 17 /*Digest username="******", realm="*/ +
				      tc_strlen(realm->realmName) + 10 /*", nonce="*/ +
					  tc_strlen(realm->param.digest.serverNonce) + 8 /*", uri="*/ +
					  tc_strlen(path) + 13 /*", response="*/ + 32 /* MD5 hash */ + 1;

				writeFn(requestStream, "Digest username=\"", 17);
				writeFn(requestStream, realm->userName, tc_strlen(realm->userName));
				writeFn(requestStream, "\", realm=\"", 10);
				writeFn(requestStream, realm->realmName, tc_strlen(realm->realmName));
				writeFn(requestStream, "\", nonce=\"", 10);
				writeFn(requestStream, realm->param.digest.serverNonce, tc_strlen(realm->param.digest.serverNonce));
				writeFn(requestStream, "\", uri=\"", 8);
				writeFn(requestStream, path, tc_strlen(path));
				writeFn(requestStream, "\", response=\"", 13);

				/*-----------------------------------------------------*/
				/* find H(A1)                                          */
				/* if (algorithm == MD5) */
				HTTP_MD5_Init(&md5Ctx);
				HTTP_MD5_Update(&md5Ctx, realm->userName, tc_strlen(realm->userName)); /* TBD!!! - what if HTTP_CHAR is not ASCII 8bit ? */
				HTTP_MD5_Update(&md5Ctx, ":", 1);
				HTTP_MD5_Update(&md5Ctx, realm->realmName, tc_strlen(realm->realmName));
				HTTP_MD5_Update(&md5Ctx, ":", 1);
				HTTP_MD5_Update(&md5Ctx, realm->password, tc_strlen(realm->password));
				HTTP_MD5_Final(&md5Ctx);

     			if (realm->param.digest.hashAlgorithm == HTTP_ALGORITHM_MD5_SESS)
				{
					HTTP_UINT8 HA1[16];

					tc_memcpy(HA1, md5Ctx.digest, 16);

					HTTP_MD5_Init(&md5Ctx);
					HTTP_MD5_Update(&md5Ctx, HA1, 16);
					HTTP_MD5_Update(&md5Ctx, ":", 1);
					HTTP_MD5_Update(&md5Ctx, realm->param.digest.serverNonce, tc_strlen(realm->param.digest.serverNonce));
					HTTP_MD5_Update(&md5Ctx, ":", 1);
					HTTP_MD5_Update(&md5Ctx, realm->param.digest.clientNonce, tc_strlen(realm->param.digest.clientNonce));
					HTTP_MD5_Final(&md5Ctx);
				}

				_HTTP_HashToHex(hashA1, md5Ctx.digest, 16);

				/*-----------------------------------------------------*/
				/* find H(A2)                                          */
				/* if (QOP == auth || QOP == none) */
				HTTP_MD5_Init(&md5Ctx);
				HTTP_MD5_Update(&md5Ctx, method, tc_strlen(method));
				HTTP_MD5_Update(&md5Ctx, ":", 1);
				HTTP_MD5_Update(&md5Ctx, path, tc_strlen(path));

				if (realm->param.digest.qop == HTTP_QOP_AUTH_INT)
				{
					HTTP_MD5_Update(&md5Ctx, ":", 1);
					/* What is HEntity!?!? */
					/*HTTP_MD5_Update(&md5Ctx, HEntity, HASHHEXLEN);*/
				}

				HTTP_MD5_Final(&md5Ctx);
				_HTTP_HashToHex(hashA2, md5Ctx.digest, 16);

				HTTP_MD5_Init(&md5Ctx);
				HTTP_MD5_Update(&md5Ctx, hashA1, 32);
				HTTP_MD5_Update(&md5Ctx, ":", 1);
				HTTP_MD5_Update(&md5Ctx, realm->param.digest.serverNonce, tc_strlen(realm->param.digest.serverNonce));
				HTTP_MD5_Update(&md5Ctx, ":", 1);

				if (realm->param.digest.qop == HTTP_QOP_AUTH ||
					realm->param.digest.qop == HTTP_QOP_AUTH_INT)
				{
					HTTP_CHAR nonceCountStr[8];

					_HTTP_UINT32ToHex(nonceCountStr, realm->param.digest.nonceCount);

					HTTP_MD5_Update(&md5Ctx, nonceCountStr, 8);
					HTTP_MD5_Update(&md5Ctx, ":", 1);
					HTTP_MD5_Update(&md5Ctx, realm->param.digest.clientNonce, tc_strlen(realm->param.digest.clientNonce));
					HTTP_MD5_Update(&md5Ctx, ":", 1);
					HTTP_MD5_Update(&md5Ctx, httpAuthQoPNames[realm->param.digest.qop], tc_strlen(httpAuthQoPNames[realm->param.digest.qop]));
					HTTP_MD5_Update(&md5Ctx, ":", 1);
				}

				HTTP_MD5_Update(&md5Ctx, hashA2, 32);
				HTTP_MD5_Final(&md5Ctx);

				_HTTP_HashToHex(finalHash, md5Ctx.digest, 16);
				finalHash[32] = '\"';

				writeFn(requestStream, finalHash, 33);

				return (len);
			}
			break;

		default:
			break;
	}

	return (0);
}
예제 #2
0
파일: debianswirl.c 프로젝트: 10crimes/code
void doSummat(void writeFn(int,int)) {
	// ...
	writeFn(12,16);
	// ...
}