[rtmpdump] branch master updated. e42b5d0 Cleanup authentication code

gitolite gil at avcodec.org
Tue Oct 30 19:18:21 CET 2012


The branch, master has been updated
       via  e42b5d0926b1a668d7fbd794a70f31040c5f198d (commit)
      from  883c33489403ed360a01d1a47ec76d476525b49e (commit)


- Log -----------------------------------------------------------------
commit e42b5d0926b1a668d7fbd794a70f31040c5f198d
Author:     Howard Chu <hyc at highlandsun.com>
AuthorDate: Tue Oct 30 11:17:41 2012 -0700
Commit:     Howard Chu <hyc at highlandsun.com>
CommitDate: Tue Oct 30 11:17:41 2012 -0700

    Cleanup authentication code
    
    from commit 9ecf540e4d5bdc85c17668fa7ead93cc375111ca

diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c
index 5ea1c76..6d04708 100644
--- a/librtmp/rtmp.c
+++ b/librtmp/rtmp.c
@@ -2497,17 +2497,16 @@ b64enc(const unsigned char *input, int length, char *output, int maxsize)
 }
 
 #ifdef USE_POLARSSL
-#define md5sum(x,y,z)  md5(x,y,z);
+#define MD5_CTX	md5_context
+#define MD5_Init(ctx)	md5_starts(ctx)
+#define MD5_Update(ctx,data,len)	md5_update(ctx,data,len)
+#define MD5_Final(dig,ctx)	md5_finish(ctx,dig)
 #elif defined(USE_GNUTLS)
-static void md5sum(const unsigned char *data, int len, unsigned char *out)
-{
-    struct md5_ctx ctx;
-    md5_init(&ctx);
-    md5_update(&ctx, len, data);
-    md5_digest(&ctx, MD5_DIGEST_LENGTH, out);
-}
+typedef struct md5_ctx	MD5_CTX
+#define MD5_Init(ctx)	md5_init(ctx)
+#define MD5_Update(ctx,data,len)	md5_update(ctx,len,data)
+#define MD5_Final(dig,ctx)	md5_digest(ctx,MD5_DIGEST_LENGTH,dig)
 #else
-#define md5sum(x,y,z)  MD5(x,y,z);
 #endif
 
 static const AVal av_authmod_adobe = AVC("authmod=adobe");
@@ -2530,10 +2529,14 @@ PublisherAuth(RTMP *r, AVal *description)
   char *token_in = NULL;
   char *ptr;
   unsigned char md5sum_val[MD5_DIGEST_LENGTH+1];
+  MD5_CTX md5ctx;
   int challenge2_data;
 #define RESPONSE_LEN 32
 #define CHALLENGE2_LEN 16
 #define SALTED2_LEN (32+8+8+8)
+#define B64DIGEST_LEN	22	/* 16 byte digest => 22 b64 chars */
+#define B64INT_LEN	6	/* 4 byte int => 6 b64 chars */
+#define HEXHASH_LEN	(2*MD5_DIGEST_LENGTH)
   char response[RESPONSE_LEN];
   char challenge2[CHALLENGE2_LEN];
   char salted2[SALTED2_LEN];
@@ -2563,11 +2566,9 @@ PublisherAuth(RTMP *r, AVal *description)
       else if((token_in = strstr(description->av_val, "?reason=needauth")) != NULL)
         {
           char *par, *val = NULL, *orig_ptr;
-          char *user = NULL;
-          char *salt = NULL;
-          char *opaque = NULL;
-          char *challenge = NULL;
-          char *salted1;
+	  AVal user, salt, opaque, challenge, *aptr = NULL;
+	  opaque.av_len = 0;
+	  challenge.av_len = 0;
 
           ptr = orig_ptr = strdup(token_in);
           while (ptr)
@@ -2581,60 +2582,72 @@ PublisherAuth(RTMP *r, AVal *description)
               if(val)
                   *val++ = '\0';
 
+	      if (aptr) {
+		aptr->av_len = par - aptr->av_val - 1;
+		aptr = NULL;
+	      }
               if (strcmp(par, "user") == 0){
-                  user = val;
+                  user.av_val = val;
+		  aptr = &user;
               } else if (strcmp(par, "salt") == 0){
-                  salt = val;
+                  salt.av_val = val;
+		  aptr = &salt;
               } else if (strcmp(par, "opaque") == 0){
-                  opaque = val;
+                  opaque.av_val = val;
+		  aptr = &opaque;
               } else if (strcmp(par, "challenge") == 0){
-                  challenge = val;
+                  challenge.av_val = val;
+		  aptr = &challenge;
               }
 
               RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val);
             }
+	  if (aptr)
+	    aptr->av_len = strlen(aptr->av_val);
+
+	  /* hash1 = base64enc(md5(user + _aodbeAuthSalt + password)) */
+	  MD5_Init(&md5ctx);
+	  MD5_Update(&md5ctx, user.av_val, user.av_len);
+	  MD5_Update(&md5ctx, salt.av_val, salt.av_len);
+	  MD5_Update(&md5ctx, r->Link.pubPasswd.av_val, r->Link.pubPasswd.av_len);
+	  MD5_Final(md5sum_val, &md5ctx);
+          RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s%s%s) =>", __FUNCTION__,
+	    user.av_val, salt.av_val, r->Link.pubPasswd.av_val);
+          RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
 
-            /* hash1 = base64enc(md5(user + _aodbeAuthSalt + password)) */
-            salted1 = malloc(strlen(user)+strlen(salt)+r->Link.pubPasswd.av_len+1);
-            strcpy(salted1, user);
-            strcat(salted1, salt);
-            strcat(salted1, r->Link.pubPasswd.av_val);
-            md5sum((unsigned char*) salted1, strlen(salted1), md5sum_val);
-            RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, salted1);
-            free(salted1);
-
-            RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
-
-            b64enc(md5sum_val, MD5_DIGEST_LENGTH, salted2, SALTED2_LEN);
-            RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_1) = %s", __FUNCTION__, salted2);
+          b64enc(md5sum_val, MD5_DIGEST_LENGTH, salted2, SALTED2_LEN);
+          RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_1) = %s", __FUNCTION__, salted2);
 
-            srand( time(NULL) );
+	/* FIXME: what byte order does this depend on? */
             challenge2_data = rand();
 
             b64enc((unsigned char *) &challenge2_data, sizeof(int), challenge2, CHALLENGE2_LEN);
             RTMP_Log(RTMP_LOGDEBUG, "%s, b64(%d) = %s", __FUNCTION__, challenge2_data, challenge2);
 
+	  MD5_Init(&md5ctx);
+	  MD5_Update(&md5ctx, salted2, B64DIGEST_LEN);
             /* response = base64enc(md5(hash1 + opaque + challenge2)) */
-            if (opaque)
-                strcat(salted2, opaque);
-            if (challenge)
-                strcat(salted2, challenge);
-            strcat(salted2, challenge2);
-
-            md5sum((unsigned char*) salted2, strlen(salted2), md5sum_val);
-            RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, salted2);
-            RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
+	  if (opaque.av_len)
+	    MD5_Update(&md5ctx, opaque.av_val, opaque.av_len);
+	  if (challenge.av_len)
+	    MD5_Update(&md5ctx, challenge.av_val, challenge.av_len);
+	  MD5_Update(&md5ctx, challenge2, B64INT_LEN);
+	  MD5_Final(md5sum_val, &md5ctx);
+
+          RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s%s%s) =>", __FUNCTION__,
+	    salted2, opaque.av_len ? opaque.av_val : "", challenge2);
+          RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
 
-            b64enc(md5sum_val, MD5_DIGEST_LENGTH, response, RESPONSE_LEN);
-            RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_2) = %s", __FUNCTION__, response);
+          b64enc(md5sum_val, MD5_DIGEST_LENGTH, response, RESPONSE_LEN);
+          RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_2) = %s", __FUNCTION__, response);
 
             /* have all hashes, create auth token for the end of app */
-            pubToken.av_val = malloc(32 + strlen(challenge2) + strlen(response) + (opaque ? strlen(opaque) : 0));
+            pubToken.av_val = malloc(32 + B64INT_LEN + B64DIGEST_LEN + opaque.av_len);
             pubToken.av_len = sprintf(pubToken.av_val,
                     "&challenge=%s&response=%s&opaque=%s",
                     challenge2,
                     response,
-                    opaque ? opaque : "");
+                    opaque.av_len ? opaque.av_val : "");
             RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val);
             free(orig_ptr);
             r->Link.pFlags |= RTMP_PUB_RESP|RTMP_PUB_CLATE;
@@ -2710,8 +2723,26 @@ PublisherAuth(RTMP *r, AVal *description)
         {
           char *orig_ptr;
           char *par, *val = NULL;
-          char *user = NULL;
-          char *nonce = NULL;
+	  char *hash1, *hash2, *hash3;
+	  AVal user, nonce, *aptr = NULL;
+	  AVal apptmp;
+
+          /* llnw auth method
+           * Seems to be closely based on HTTP Digest Auth:
+           *    http://tools.ietf.org/html/rfc2617
+           *    http://en.wikipedia.org/wiki/Digest_access_authentication
+           */
+
+          const char authmod[] = "llnw";
+          const char realm[] = "live";
+          const char method[] = "publish";
+          const char qop[] = "auth";
+          /* nc = 1..connection count (or rather, number of times cnonce has been reused) */
+          int nc = 1;
+          /* nchex = hexenc(nc) (8 hex digits according to RFC 2617) */
+          char nchex[9];
+          /* cnonce = hexenc(4 random bytes) (initialized on first connection) */
+          char cnonce[9];
 
           ptr = orig_ptr = strdup(token_in);
           /* Extract parameters (we need user and nonce) */
@@ -2726,82 +2757,84 @@ PublisherAuth(RTMP *r, AVal *description)
               if(val)
                   *val++ = '\0';
 
+	      if (aptr) {
+		aptr->av_len = par - aptr->av_val - 1;
+		aptr = NULL;
+	      }
               if (strcmp(par, "user") == 0){
-                  user = val;
+                user.av_val = val;
+		aptr = &user;
               } else if (strcmp(par, "nonce") == 0){
-                  nonce = val;
+                nonce.av_val = val;
+		aptr = &nonce;
               }
 
               RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val);
             }
+	  if (aptr)
+	    aptr->av_len = strlen(aptr->av_val);
 
-          // FIXME: handle case where user==NULL or nonce==NULL
-
-          /* llnw auth method
-           * Seems to be closely based on HTTP Digest Auth:
-           *    http://tools.ietf.org/html/rfc2617
-           *    http://en.wikipedia.org/wiki/Digest_access_authentication
-           */
-
-          const char *authmod = "llnw";
-          const char *realm = "live";
-          const char *method = "publish";
-          const char *qop = "auth";
-          char *tmpbuf;
+          /* FIXME: handle case where user==NULL or nonce==NULL */
 
-          /* nc = 1..connection count (or rather, number of times cnonce has been reused) */
-          int nc = 1;
-          /* nchex = hexenc(nc) (8 hex digits according to RFC 2617) */
-          char nchex[9];
           sprintf(nchex, "%08x", nc);
-          /* cnonce = hexenc(4 random bytes) (initialized on first connection) */
-          char cnonce[9];
-          srand( time(NULL) ); // FIXME: a lib shouldn't call srand()
           sprintf(cnonce, "%08x", rand());
 
           /* hash1 = hexenc(md5(user + ":" + realm + ":" + password)) */
-          tmpbuf = malloc(strlen(user) + 1 + strlen(realm) + 1 + r->Link.pubPasswd.av_len + 1);
-          sprintf(tmpbuf, "%s:%s:%s", user, realm, r->Link.pubPasswd.av_val);
-          md5sum((unsigned char*)tmpbuf, strlen(tmpbuf), md5sum_val);
-          RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, tmpbuf);
+	  MD5_Init(&md5ctx);
+	  MD5_Update(&md5ctx, user.av_val, user.av_len);
+	  MD5_Update(&md5ctx, ":", 1);
+	  MD5_Update(&md5ctx, realm, sizeof(realm)-1);
+	  MD5_Update(&md5ctx, ":", 1);
+	  MD5_Update(&md5ctx, r->Link.pubPasswd.av_val, r->Link.pubPasswd.av_len);
+	  MD5_Final(md5sum_val, &md5ctx);
+          RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s) =>", __FUNCTION__,
+	    user.av_val, realm, r->Link.pubPasswd.av_val);
           RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
-          free(tmpbuf);
-          char *hash1 = hexenc(md5sum_val, MD5_DIGEST_LENGTH);
+          hash1 = hexenc(md5sum_val, MD5_DIGEST_LENGTH);
 
           /* hash2 = hexenc(md5(method + ":/" + app + "/" + appInstance)) */
           /* Extract appname + appinstance without query parameters */
-          char *apptmp = malloc(r->Link.app.av_len + 1), *qpos;
-          memcpy(apptmp, r->Link.app.av_val, r->Link.app.av_len);
-          apptmp[r->Link.app.av_len] = '\0';
-          if((qpos = strchr(apptmp, '?')))
-              *qpos = '\0';
-
-          tmpbuf = malloc(strlen(method) + 2 + strlen(apptmp) + 1);
-          sprintf(tmpbuf, "%s:/%s", method, apptmp);
-          md5sum((unsigned char*)tmpbuf, strlen(tmpbuf), md5sum_val);
-          RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, tmpbuf);
+	  apptmp = r->Link.app;
+	  ptr = strchr(apptmp.av_val, '?');
+	  if (ptr)
+	    apptmp.av_len = ptr - apptmp.av_val;
+
+	  MD5_Init(&md5ctx);
+	  MD5_Update(&md5ctx, method, sizeof(method)-1);
+	  MD5_Update(&md5ctx, ":/", 2);
+	  MD5_Update(&md5ctx, apptmp.av_val, apptmp.av_len);
+	  MD5_Final(md5sum_val, &md5ctx);
+          RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:/%.*s) =>", __FUNCTION__,
+	    method, apptmp.av_len, apptmp.av_val);
           RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
-          free(tmpbuf);
-          char *hash2 = hexenc(md5sum_val, MD5_DIGEST_LENGTH);
-
-          free(apptmp);
+          hash2 = hexenc(md5sum_val, MD5_DIGEST_LENGTH);
 
           /* hash3 = hexenc(md5(hash1 + ":" + nonce + ":" + nchex + ":" + cnonce + ":" + qop + ":" + hash2)) */
-          tmpbuf = malloc(strlen(hash1) + 1 + strlen(nonce) + 1 + strlen(nchex) + 1 + strlen(cnonce) + 1 + strlen(qop) + 1 + strlen(hash2) + 1);
-          sprintf(tmpbuf, "%s:%s:%s:%s:%s:%s", hash1, nonce, nchex, cnonce, qop, hash2);
-          md5sum((unsigned char*)tmpbuf, strlen(tmpbuf), md5sum_val);
-          RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, tmpbuf);
+	  MD5_Init(&md5ctx);
+	  MD5_Update(&md5ctx, hash1, HEXHASH_LEN);
+	  MD5_Update(&md5ctx, ":", 1);
+	  MD5_Update(&md5ctx, nonce.av_val, nonce.av_len);
+	  MD5_Update(&md5ctx, ":", 1);
+	  MD5_Update(&md5ctx, nchex, sizeof(nchex)-1);
+	  MD5_Update(&md5ctx, ":", 1);
+	  MD5_Update(&md5ctx, cnonce, sizeof(cnonce)-1);
+	  MD5_Update(&md5ctx, ":", 1);
+	  MD5_Update(&md5ctx, qop, sizeof(qop)-1);
+	  MD5_Update(&md5ctx, ":", 1);
+	  MD5_Update(&md5ctx, hash2, HEXHASH_LEN);
+	  MD5_Final(md5sum_val, &md5ctx);
+          RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s:%s:%s:%s) =>", __FUNCTION__,
+	    hash1, nonce.av_val, nchex, cnonce, qop, hash2);
           RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
-          free(tmpbuf);
-          char *hash3 = hexenc(md5sum_val, MD5_DIGEST_LENGTH);
+          hash3 = hexenc(md5sum_val, MD5_DIGEST_LENGTH);
 
           /* pubToken = &authmod=<authmod>&user=<username>&nonce=<nonce>&cnonce=<cnonce>&nc=<nchex>&response=<hash3> */
           /* Append nonces and response to query string which already contains
            * user + authmod */
-          pubToken.av_val = malloc(64 + strlen(authmod) + strlen(user) + strlen(nonce) + strlen(cnonce) + strlen(nchex) + strlen(hash3));
+          pubToken.av_val = malloc(64 + sizeof(authmod)-1 + user.av_len + nonce.av_len + sizeof(cnonce)-1 + sizeof(nchex)-1 + HEXHASH_LEN);
           sprintf(pubToken.av_val,
                   "&nonce=%s&cnonce=%s&nc=%s&response=%s",
-                  nonce, cnonce, nchex, hash3);
+                  nonce.av_val, cnonce, nchex, hash3);
           pubToken.av_len = strlen(pubToken.av_val);
           RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val);
           r->Link.pFlags |= RTMP_PUB_RESP|RTMP_PUB_CLATE;

-----------------------------------------------------------------------

Summary of changes:
 librtmp/rtmp.c |  227 ++++++++++++++++++++++++++++++++------------------------
 1 files changed, 130 insertions(+), 97 deletions(-)


hooks/post-receive
-- 



More information about the rtmpdump mailing list