📄 http.c
字号:
/* Clean */ free( current_cookie_name ); free( current_cookie_domain ); break; } free( current_cookie_name ); free( current_cookie_domain ); } free( cookie_name ); free( cookie_domain ); vlc_array_append( cookies, cookie );}/***************************************************************************** * "RFC 2617: Basic and Digest Access Authentication" header parsing *****************************************************************************/static char *AuthGetParam( const char *psz_header, const char *psz_param ){ char psz_what[strlen(psz_param)+3]; sprintf( psz_what, "%s=\"", psz_param ); psz_header = strstr( psz_header, psz_what ); if( psz_header ) { const char *psz_end; psz_header += strlen( psz_what ); psz_end = strchr( psz_header, '"' ); if( !psz_end ) /* Invalid since we should have a closing quote */ return strdup( psz_header ); return strndup( psz_header, psz_end - psz_header ); } else { return NULL; }}static char *AuthGetParamNoQuotes( const char *psz_header, const char *psz_param ){ char psz_what[strlen(psz_param)+2]; sprintf( psz_what, "%s=", psz_param ); psz_header = strstr( psz_header, psz_what ); if( psz_header ) { const char *psz_end; psz_header += strlen( psz_what ); psz_end = strchr( psz_header, ',' ); /* XXX: Do we need to filter out trailing space between the value and * the comma/end of line? */ if( !psz_end ) /* Can be valid if this is the last parameter */ return strdup( psz_header ); return strndup( psz_header, psz_end - psz_header ); } else { return NULL; }}static void AuthParseHeader( access_t *p_access, const char *psz_header, http_auth_t *p_auth ){ /* FIXME: multiple auth methods can be listed (comma seperated) */ /* 2 Basic Authentication Scheme */ if( !strncasecmp( psz_header, "Basic ", strlen( "Basic " ) ) ) { msg_Dbg( p_access, "Using Basic Authentication" ); psz_header += strlen( "Basic " ); p_auth->psz_realm = AuthGetParam( psz_header, "realm" ); if( !p_auth->psz_realm ) msg_Warn( p_access, "Basic Authentication: " "Mandatory 'realm' parameter is missing" ); } /* 3 Digest Access Authentication Scheme */ else if( !strncasecmp( psz_header, "Digest ", strlen( "Digest " ) ) ) { msg_Dbg( p_access, "Using Digest Access Authentication" ); if( p_auth->psz_nonce ) return; /* FIXME */ psz_header += strlen( "Digest " ); p_auth->psz_realm = AuthGetParam( psz_header, "realm" ); p_auth->psz_domain = AuthGetParam( psz_header, "domain" ); p_auth->psz_nonce = AuthGetParam( psz_header, "nonce" ); p_auth->psz_opaque = AuthGetParam( psz_header, "opaque" ); p_auth->psz_stale = AuthGetParamNoQuotes( psz_header, "stale" ); p_auth->psz_algorithm = AuthGetParamNoQuotes( psz_header, "algorithm" ); p_auth->psz_qop = AuthGetParam( psz_header, "qop" ); p_auth->i_nonce = 0; /* printf("realm: |%s|\ndomain: |%s|\nnonce: |%s|\nopaque: |%s|\n" "stale: |%s|\nalgorithm: |%s|\nqop: |%s|\n", p_auth->psz_realm,p_auth->psz_domain,p_auth->psz_nonce, p_auth->psz_opaque,p_auth->psz_stale,p_auth->psz_algorithm, p_auth->psz_qop); */ if( !p_auth->psz_realm ) msg_Warn( p_access, "Digest Access Authentication: " "Mandatory 'realm' parameter is missing" ); if( !p_auth->psz_nonce ) msg_Warn( p_access, "Digest Access Authentication: " "Mandatory 'nonce' parameter is missing" ); if( p_auth->psz_qop ) /* FIXME: parse the qop list */ { char *psz_tmp = strchr( p_auth->psz_qop, ',' ); if( psz_tmp ) *psz_tmp = '\0'; } } else { const char *psz_end = strchr( psz_header, ' ' ); if( psz_end ) msg_Warn( p_access, "Unknown authentication scheme: '%*s'", psz_end - psz_header, psz_header ); else msg_Warn( p_access, "Unknown authentication scheme: '%s'", psz_header ); }}static char *AuthDigest( access_t *p_access, vlc_url_t *p_url, http_auth_t *p_auth, const char *psz_method ){ (void)p_access; const char *psz_username = p_url->psz_username ?: ""; const char *psz_password = p_url->psz_password ?: ""; char *psz_HA1 = NULL; char *psz_HA2 = NULL; char *psz_response = NULL; struct md5_s md5; /* H(A1) */ if( p_auth->psz_HA1 ) { psz_HA1 = strdup( p_auth->psz_HA1 ); if( !psz_HA1 ) goto error; } else { InitMD5( &md5 ); AddMD5( &md5, psz_username, strlen( psz_username ) ); AddMD5( &md5, ":", 1 ); AddMD5( &md5, p_auth->psz_realm, strlen( p_auth->psz_realm ) ); AddMD5( &md5, ":", 1 ); AddMD5( &md5, psz_password, strlen( psz_password ) ); EndMD5( &md5 ); psz_HA1 = psz_md5_hash( &md5 ); if( !psz_HA1 ) goto error; if( p_auth->psz_algorithm && !strcmp( p_auth->psz_algorithm, "MD5-sess" ) ) { InitMD5( &md5 ); AddMD5( &md5, psz_HA1, 32 ); free( psz_HA1 ); AddMD5( &md5, ":", 1 ); AddMD5( &md5, p_auth->psz_nonce, strlen( p_auth->psz_nonce ) ); AddMD5( &md5, ":", 1 ); AddMD5( &md5, p_auth->psz_cnonce, strlen( p_auth->psz_cnonce ) ); EndMD5( &md5 ); psz_HA1 = psz_md5_hash( &md5 ); if( !psz_HA1 ) goto error; p_auth->psz_HA1 = strdup( psz_HA1 ); if( !p_auth->psz_HA1 ) goto error; } } /* H(A2) */ InitMD5( &md5 ); if( *psz_method ) AddMD5( &md5, psz_method, strlen( psz_method ) ); AddMD5( &md5, ":", 1 ); if( p_url->psz_path ) AddMD5( &md5, p_url->psz_path, strlen( p_url->psz_path ) ); else AddMD5( &md5, "/", 1 ); if( p_auth->psz_qop && !strcmp( p_auth->psz_qop, "auth-int" ) ) { char *psz_ent; struct md5_s ent; InitMD5( &ent ); AddMD5( &ent, "", 0 ); /* XXX: entity-body. should be ok for GET */ EndMD5( &ent ); psz_ent = psz_md5_hash( &ent ); if( !psz_ent ) goto error; AddMD5( &md5, ":", 1 ); AddMD5( &md5, psz_ent, 32 ); free( psz_ent ); } EndMD5( &md5 ); psz_HA2 = psz_md5_hash( &md5 ); if( !psz_HA2 ) goto error; /* Request digest */ InitMD5( &md5 ); AddMD5( &md5, psz_HA1, 32 ); AddMD5( &md5, ":", 1 ); AddMD5( &md5, p_auth->psz_nonce, strlen( p_auth->psz_nonce ) ); AddMD5( &md5, ":", 1 ); if( p_auth->psz_qop && ( !strcmp( p_auth->psz_qop, "auth" ) || !strcmp( p_auth->psz_qop, "auth-int" ) ) ) { char psz_inonce[9]; snprintf( psz_inonce, 9, "%08x", p_auth->i_nonce ); AddMD5( &md5, psz_inonce, 8 ); AddMD5( &md5, ":", 1 ); AddMD5( &md5, p_auth->psz_cnonce, strlen( p_auth->psz_cnonce ) ); AddMD5( &md5, ":", 1 ); AddMD5( &md5, p_auth->psz_qop, strlen( p_auth->psz_qop ) ); AddMD5( &md5, ":", 1 ); } AddMD5( &md5, psz_HA2, 32 ); EndMD5( &md5 ); psz_response = psz_md5_hash( &md5 ); error: free( psz_HA1 ); free( psz_HA2 ); return psz_response;}static void AuthReply( access_t *p_access, const char *psz_prefix, vlc_url_t *p_url, http_auth_t *p_auth ){ access_sys_t *p_sys = p_access->p_sys; v_socket_t *pvs = p_sys->p_vs; const char *psz_username = p_url->psz_username ?: ""; const char *psz_password = p_url->psz_password ?: ""; if( p_auth->psz_nonce ) { /* Digest Access Authentication */ char *psz_response; if( p_auth->psz_algorithm && strcmp( p_auth->psz_algorithm, "MD5" ) && strcmp( p_auth->psz_algorithm, "MD5-sess" ) ) { msg_Err( p_access, "Digest Access Authentication: " "Unknown algorithm '%s'", p_auth->psz_algorithm ); return; } if( p_auth->psz_qop || !p_auth->psz_cnonce ) { /* FIXME: needs to be really random to prevent man in the middle * attacks */ free( p_auth->psz_cnonce ); p_auth->psz_cnonce = strdup( "Some random string FIXME" ); } p_auth->i_nonce ++; psz_response = AuthDigest( p_access, p_url, p_auth, "GET" ); if( !psz_response ) return; net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "%sAuthorization: Digest " /* Mandatory parameters */ "username=\"%s\", " "realm=\"%s\", " "nonce=\"%s\", " "uri=\"%s\", " "response=\"%s\", " /* Optional parameters */ "%s%s%s" /* algorithm */ "%s%s%s" /* cnonce */ "%s%s%s" /* opaque */ "%s%s%s" /* message qop */ "%s%08x%s" /* nonce count */ "\r\n", /* Mandatory parameters */ psz_prefix, psz_username, p_auth->psz_realm, p_auth->psz_nonce, p_url->psz_path ?: "/", psz_response, /* Optional parameters */ p_auth->psz_algorithm ? "algorithm=\"" : "", p_auth->psz_algorithm ?: "", p_auth->psz_algorithm ? "\", " : "", p_auth->psz_cnonce ? "cnonce=\"" : "", p_auth->psz_cnonce ?: "", p_auth->psz_cnonce ? "\", " : "", p_auth->psz_opaque ? "opaque=\"" : "", p_auth->psz_opaque ?: "", p_auth->psz_opaque ? "\", " : "", p_auth->psz_qop ? "qop=\"" : "", p_auth->psz_qop ?: "", p_auth->psz_qop ? "\", " : "", p_auth->i_nonce ? "nc=\"" : "uglyhack=\"", /* Will be parsed as an unhandled extension */ p_auth->i_nonce, p_auth->i_nonce ? "\"" : "\"" ); free( psz_response ); } else { /* Basic Access Authentication */ char buf[strlen( psz_username ) + strlen( psz_password ) + 2]; char *b64; snprintf( buf, sizeof( buf ), "%s:%s", psz_username, psz_password ); b64 = vlc_b64_encode( buf ); if( b64 != NULL ) { net_Printf( VLC_OBJECT(p_access), p_sys->fd, pvs, "%sAuthorization: Basic %s\r\n", psz_prefix, b64 ); free( b64 ); } }}static int AuthCheckReply( access_t *p_access, const char *psz_header, vlc_url_t *p_url, http_auth_t *p_auth ){ int i_ret = VLC_EGENERIC; char *psz_nextnonce = AuthGetParam( psz_header, "nextnonce" ); char *psz_qop = AuthGetParamNoQuotes( psz_header, "qop" ); char *psz_rspauth = AuthGetParam( psz_header, "rspauth" ); char *psz_cnonce = AuthGetParam( psz_header, "cnonce" ); char *psz_nc = AuthGetParamNoQuotes( psz_header, "nc" ); if( psz_cnonce ) { char *psz_digest; if( strcmp( psz_cnonce, p_auth->psz_cnonce ) ) { msg_Err( p_access, "HTTP Digest Access Authentication: server replied with a different client nonce value." ); goto error; } if( psz_nc ) { int i_nonce; i_nonce = strtol( psz_nc, NULL, 16 ); if( i_nonce != p_auth->i_nonce ) { msg_Err( p_access, "HTTP Digest Access Authentication: server replied with a different nonce count value." ); goto error; } } if( psz_qop && p_auth->psz_qop && strcmp( psz_qop, p_auth->psz_qop ) ) msg_Warn( p_access, "HTTP Digest Access Authentication: server replied using a different 'quality of protection' option" ); /* All the clear text values match, let's now check the response * digest */ psz_digest = AuthDigest( p_access, p_url, p_auth, "" ); if( strcmp( psz_digest, psz_rspauth ) ) { msg_Err( p_access, "HTTP Digest Access Authentication: server replied with an invalid response digest (expected value: %s).", psz_digest ); free( psz_digest ); goto error; } free( psz_digest ); } if( psz_nextnonce ) { free( p_auth->psz_nonce ); p_auth->psz_nonce = psz_nextnonce; psz_nextnonce = NULL; } i_ret = VLC_SUCCESS; error: free( psz_nextnonce ); free( psz_qop ); free( psz_rspauth ); free( psz_cnonce ); free( psz_nc ); return i_ret;}static void AuthReset( http_auth_t *p_auth ){ FREENULL( p_auth->psz_realm ); FREENULL( p_auth->psz_domain ); FREENULL( p_auth->psz_nonce ); FREENULL( p_auth->psz_opaque ); FREENULL( p_auth->psz_stale ); FREENULL( p_auth->psz_algorithm ); FREENULL( p_auth->psz_qop ); p_auth->i_nonce = 0; FREENULL( p_auth->psz_cnonce ); FREENULL( p_auth->psz_HA1 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -