/* Performs login with existing credentials and ask the user for new ones on failure */ static int login( stream_t *p_access ) { int i_ret = VLC_EGENERIC; access_sys_t *p_sys = p_access->p_sys; vlc_credential credential; char *psz_var_domain; const char *psz_login, *psz_password, *psz_domain; bool b_guest = false; vlc_credential_init( &credential, &p_sys->url ); psz_var_domain = var_InheritString( p_access, "smb-domain" ); credential.psz_realm = psz_var_domain ? psz_var_domain : NULL; vlc_credential_get( &credential, p_access, "smb-user", "smb-pwd", NULL, NULL ); if( !credential.psz_username ) { psz_login = "******"; psz_password = ""; b_guest = true; } else { psz_login = credential.psz_username; psz_password = credential.psz_password; } psz_domain = credential.psz_realm ? credential.psz_realm : p_sys->netbios_name; /* Try to authenticate on the remote machine */ if( smb_connect( p_access, psz_login, psz_password, psz_domain ) != VLC_SUCCESS ) { while( vlc_credential_get( &credential, p_access, "smb-user", "smb-pwd", SMB_LOGIN_DIALOG_TITLE, SMB_LOGIN_DIALOG_TEXT, p_sys->netbios_name ) ) { b_guest = false; psz_login = credential.psz_username; psz_password = credential.psz_password; psz_domain = credential.psz_realm ? credential.psz_realm : p_sys->netbios_name; if( smb_connect( p_access, psz_login, psz_password, psz_domain ) == VLC_SUCCESS ) goto success; } msg_Err( p_access, "Unable to login" ); goto error; } else if( smb_session_is_guest( p_sys->p_session ) == 1 ) { msg_Warn( p_access, "Login failure but you were logged in as a Guest"); b_guest = true; } success: msg_Warn( p_access, "Creds: username = '******', domain = '%s'", psz_login, psz_domain ); if( !b_guest ) vlc_credential_store( &credential, p_access ); i_ret = VLC_SUCCESS; error: vlc_credential_clean( &credential ); free( psz_var_domain ); return i_ret; }
/**************************************************************************** * Open: connect to smb server and ask for file ****************************************************************************/ static int Open( vlc_object_t *p_this ) { stream_t *p_access = (stream_t*)p_this; access_sys_t *p_sys; struct stat filestat; vlc_url_t url; vlc_credential credential; char *psz_decoded_path = NULL, *psz_uri = NULL, *psz_var_domain = NULL; int i_ret; int i_smb; uint64_t i_size; bool b_is_dir = false; #ifndef _WIN32 if( smbc_init( smb_auth, 0 ) ) return VLC_EGENERIC; #endif /* ** some version of glibc defines open as a macro, causing havoc ** with other macros using 'open' under the hood, such as the ** following one: */ #if defined(smbc_open) && defined(open) # undef open #endif vlc_UrlParse( &url, p_access->psz_url ); if( url.psz_path ) { psz_decoded_path = vlc_uri_decode_duplicate( url.psz_path ); if( !psz_decoded_path ) { vlc_UrlClean( &url ); return VLC_EGENERIC; } } vlc_credential_init( &credential, &url ); psz_var_domain = var_InheritString( p_access, "smb-domain" ); credential.psz_realm = psz_var_domain; vlc_credential_get( &credential, p_access, "smb-user", "smb-pwd", NULL, NULL ); for (;;) { if( smb_get_uri( p_access, &psz_uri, credential.psz_realm, credential.psz_username, credential.psz_password, url.psz_host, psz_decoded_path, NULL ) == -1 ) { vlc_credential_clean( &credential ); free(psz_var_domain); free( psz_decoded_path ); vlc_UrlClean( &url ); return VLC_ENOMEM; } if( ( i_ret = smbc_stat( psz_uri, &filestat ) ) && errno == EACCES ) { errno = 0; if( vlc_credential_get( &credential, p_access, "smb-user", "smb-pwd", SMB_LOGIN_DIALOG_TITLE, SMB_LOGIN_DIALOG_TEXT, url.psz_host) ) continue; } /* smbc_stat fails with servers or shares. Assume they are directory */ if( i_ret || S_ISDIR( filestat.st_mode ) ) b_is_dir = true; break; } vlc_credential_store( &credential, p_access ); vlc_credential_clean( &credential ); free(psz_var_domain); free( psz_decoded_path ); /* Init p_access */ p_sys = p_access->p_sys = vlc_calloc( p_this, 1, sizeof( access_sys_t ) ); if( !p_sys ) { free( psz_uri ); vlc_UrlClean( &url ); return VLC_ENOMEM; } if( b_is_dir ) { p_sys->url = url; p_access->pf_readdir = DirRead; p_access->pf_control = access_vaDirectoryControlHelper; i_size = 0; #ifndef _WIN32 i_smb = smbc_opendir( psz_uri ); if( i_smb < 0 ) vlc_UrlClean( &p_sys->url ); #endif } else { ACCESS_SET_CALLBACKS( Read, NULL, Control, Seek ); i_smb = smbc_open( psz_uri, O_RDONLY, 0 ); i_size = filestat.st_size; vlc_UrlClean( &url ); } free( psz_uri ); #ifndef _WIN32 if( i_smb < 0 ) { msg_Err( p_access, "open failed for '%s' (%s)", p_access->psz_location, vlc_strerror_c(errno) ); return VLC_EGENERIC; } #endif p_sys->size = i_size; p_sys->i_smb = i_smb; return VLC_SUCCESS; }
/***************************************************************************** * Open: *****************************************************************************/ static int Open( vlc_object_t *p_this ) { stream_t *p_access = (stream_t*)p_this; const char *psz_url = p_access->psz_url; char *psz; int ret = VLC_EGENERIC; vlc_credential credential; access_sys_t *p_sys = vlc_obj_malloc( p_this, sizeof(*p_sys) ); if( unlikely(p_sys == NULL) ) return VLC_ENOMEM; p_sys->stream = NULL; p_sys->b_proxy = false; p_sys->psz_proxy_passbuf = NULL; p_sys->psz_mime = NULL; p_sys->b_icecast = false; p_sys->psz_location = NULL; p_sys->psz_user_agent = NULL; p_sys->psz_referrer = NULL; p_sys->psz_username = NULL; p_sys->psz_password = NULL; p_sys->i_icy_meta = 0; p_sys->i_icy_offset = 0; p_sys->psz_icy_name = NULL; p_sys->psz_icy_genre = NULL; p_sys->psz_icy_title = NULL; p_sys->b_has_size = false; p_sys->offset = 0; p_sys->size = 0; p_access->p_sys = p_sys; if( vlc_UrlParse( &p_sys->url, psz_url ) || p_sys->url.psz_host == NULL ) { msg_Err( p_access, "invalid URL" ); vlc_UrlClean( &p_sys->url ); return VLC_EGENERIC; } if( p_sys->url.i_port <= 0 ) p_sys->url.i_port = 80; vlc_credential_init( &credential, &p_sys->url ); /* Determine the HTTP user agent */ /* See RFC2616 §2.2 token and comment definition, and §3.8 and * §14.43 user-agent header */ p_sys->psz_user_agent = var_InheritString( p_access, "http-user-agent" ); if (p_sys->psz_user_agent) { unsigned comment_level = 0; for( char *p = p_sys->psz_user_agent; *p; p++ ) { uint8_t c = *p; if (comment_level == 0) { if( c < 32 || strchr( ")<>@,;:\\\"[]?={}", c ) ) *p = '_'; /* remove potentially harmful characters */ } else { if (c == ')') comment_level--; else if( c < 32 && strchr( "\t\r\n", c ) == NULL) *p = '_'; /* remove potentially harmful characters */ } if (c == '(') { if (comment_level == UINT_MAX) break; comment_level++; } } /* truncate evil unclosed comments */ if (comment_level > 0) { char *p = strchr(p_sys->psz_user_agent, '('); *p = '\0'; } } /* HTTP referrer */ p_sys->psz_referrer = var_InheritString( p_access, "http-referrer" ); /* Check proxy */ psz = var_InheritString( p_access, "http-proxy" ); if( psz == NULL ) { msg_Dbg(p_access, "querying proxy for %s", psz_url); psz = vlc_getProxyUrl(psz_url); if (psz != NULL) msg_Dbg(p_access, "proxy: %s", psz); else msg_Dbg(p_access, "no proxy"); } if( psz != NULL ) { p_sys->b_proxy = true; vlc_UrlParse( &p_sys->proxy, psz ); free( psz ); psz = var_InheritString( p_access, "http-proxy-pwd" ); if( psz ) p_sys->proxy.psz_password = p_sys->psz_proxy_passbuf = psz; if( p_sys->proxy.psz_host == NULL || *p_sys->proxy.psz_host == '\0' ) { msg_Warn( p_access, "invalid proxy host" ); goto error; } if( p_sys->proxy.i_port <= 0 ) { p_sys->proxy.i_port = 80; } } msg_Dbg( p_access, "http: server='%s' port=%d file='%s'", p_sys->url.psz_host, p_sys->url.i_port, p_sys->url.psz_path != NULL ? p_sys->url.psz_path : "" ); if( p_sys->b_proxy ) { msg_Dbg( p_access, " proxy %s:%d", p_sys->proxy.psz_host, p_sys->proxy.i_port ); } if( p_sys->url.psz_username && *p_sys->url.psz_username ) { msg_Dbg( p_access, " user='******'", p_sys->url.psz_username ); } p_sys->b_reconnect = var_InheritBool( p_access, "http-reconnect" ); if( vlc_credential_get( &credential, p_access, NULL, NULL, NULL, NULL ) ) { p_sys->url.psz_username = (char *) credential.psz_username; p_sys->url.psz_password = (char *) credential.psz_password; } connect: /* Connect */ if( Connect( p_access ) ) goto disconnect; if( p_sys->i_code == 401 ) { if( p_sys->auth.psz_realm == NULL ) { msg_Err( p_access, "authentication failed without realm" ); goto disconnect; } /* FIXME ? */ if( p_sys->url.psz_username && p_sys->url.psz_password && p_sys->auth.psz_nonce && p_sys->auth.i_nonce == 0 ) { Disconnect( p_access ); goto connect; } free( p_sys->psz_username ); free( p_sys->psz_password ); p_sys->psz_username = p_sys->psz_password = NULL; msg_Dbg( p_access, "authentication failed for realm %s", p_sys->auth.psz_realm ); credential.psz_realm = p_sys->auth.psz_realm; credential.psz_authtype = p_sys->auth.psz_nonce ? "Digest" : "Basic"; if( vlc_credential_get( &credential, p_access, NULL, NULL, _("HTTP authentication"), _("Please enter a valid login name and a " "password for realm %s."), p_sys->auth.psz_realm ) ) { p_sys->psz_username = strdup(credential.psz_username); p_sys->psz_password = strdup(credential.psz_password); if (!p_sys->psz_username || !p_sys->psz_password) goto disconnect; msg_Err( p_access, "retrying with user=%s", p_sys->psz_username ); p_sys->url.psz_username = p_sys->psz_username; p_sys->url.psz_password = p_sys->psz_password; Disconnect( p_access ); goto connect; } else goto disconnect; } else vlc_credential_store( &credential, p_access ); if( ( p_sys->i_code == 301 || p_sys->i_code == 302 || p_sys->i_code == 303 || p_sys->i_code == 307 ) && p_sys->psz_location != NULL ) { p_access->psz_url = p_sys->psz_location; p_sys->psz_location = NULL; ret = VLC_ACCESS_REDIRECT; goto disconnect; } if( p_sys->b_reconnect ) msg_Dbg( p_access, "auto re-connect enabled" ); /* Set up p_access */ p_access->pf_read = Read; p_access->pf_control = Control; p_access->pf_seek = Seek; vlc_credential_clean( &credential ); return VLC_SUCCESS; disconnect: Disconnect( p_access ); error: vlc_credential_clean( &credential ); vlc_UrlClean( &p_sys->url ); if( p_sys->b_proxy ) vlc_UrlClean( &p_sys->proxy ); free( p_sys->psz_proxy_passbuf ); free( p_sys->psz_mime ); free( p_sys->psz_location ); free( p_sys->psz_user_agent ); free( p_sys->psz_referrer ); free( p_sys->psz_username ); free( p_sys->psz_password ); return ret; }
static int Open(vlc_object_t *obj) { stream_t *access = (stream_t *)obj; vlc_url_t url; vlc_credential credential; char *psz_decoded_path = NULL, *psz_uri = NULL, *psz_var_domain = NULL; int fd; uint64_t size; bool is_dir; if (vlc_UrlParseFixup(&url, access->psz_url) != 0) { vlc_UrlClean(&url); return VLC_EGENERIC; } if (url.psz_path != NULL) { psz_decoded_path = vlc_uri_decode_duplicate(url.psz_path); if (psz_decoded_path == NULL) { vlc_UrlClean(&url); return VLC_EGENERIC; } } vlc_credential_init(&credential, &url); psz_var_domain = var_InheritString(access, "smb-domain"); credential.psz_realm = psz_var_domain; vlc_credential_get(&credential, access, "smb-user", "smb-pwd", NULL, NULL); for (;;) { struct stat st; if (smb_get_uri(access, &psz_uri, credential.psz_realm, credential.psz_username, credential.psz_password, url.psz_host, psz_decoded_path, NULL ) == -1 ) { vlc_credential_clean(&credential); free(psz_var_domain); free(psz_decoded_path); vlc_UrlClean(&url); return VLC_ENOMEM; } if (stat(psz_uri, &st) == 0) { is_dir = S_ISDIR(st.st_mode) != 0; size = st.st_size; break; } /* stat() fails with servers or shares. Assume directory. */ is_dir = true; size = 0; if (errno != EACCES) break; errno = 0; if (!vlc_credential_get(&credential, access, "smb-user", "smb-pwd", SMB_LOGIN_DIALOG_TITLE, SMB_LOGIN_DIALOG_TEXT, url.psz_host)) break; } vlc_credential_store(&credential, access); vlc_credential_clean(&credential); free(psz_var_domain); free(psz_decoded_path); /* Init access */ access_sys_t *sys = vlc_obj_calloc(obj, 1, sizeof (*sys)); if (unlikely(sys == NULL)) { free(psz_uri); vlc_UrlClean(&url); return VLC_ENOMEM; } access->p_sys = sys; if (is_dir) { sys->url = url; access->pf_readdir = DirRead; access->pf_control = access_vaDirectoryControlHelper; } else { access->pf_read = Read; access->pf_control = Control; access->pf_seek = Seek; fd = open(psz_uri, O_RDONLY, 0); vlc_UrlClean(&url); } free(psz_uri); sys->size = size; sys->i_smb = fd; return VLC_SUCCESS; }