Implement XDG compliance, logging, and improved 401 error handling
- Install to ~/.local/bin/winamp-mpris - Use ~/.local/state/winamp-mpris/bridge.log for logging - Use $XDG_RUNTIME_DIR/winamp-mpris.pid for PID management - Add detailed user notification for 401 Unauthorized errors - Add install.sh for automated, standard-compliant setup - Include Winamp Web Interface source code and installer in repository
This commit is contained in:
312
Wawi Source/security.cpp
Normal file
312
Wawi Source/security.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
/* --- SECURITY.CPP ---
|
||||
/
|
||||
/ Written by Phil Himsworth, 2001-2002.
|
||||
/
|
||||
/*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "main.h"
|
||||
#include "html.h"
|
||||
#include "plugin.h"
|
||||
|
||||
extern char password[], username[];
|
||||
extern int securepassword;
|
||||
|
||||
extern winampGeneralPurposePlugin plugin;
|
||||
|
||||
|
||||
|
||||
// Base64 character array
|
||||
// 0 1 2 3 4 5 6
|
||||
// 01234567890123456789012345678901234567890123456789012345678901234
|
||||
char bchars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+*";
|
||||
char achars[256];
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Calculates MD5 of a string
|
||||
bool MD5(char * input, char * output, int output_len)
|
||||
{
|
||||
//MessageBox(NULL,input,"MD5 input",MB_TOPMOST | MB_OK);
|
||||
HCRYPTPROV hProv = 0;
|
||||
HCRYPTHASH Hash;
|
||||
|
||||
if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
// Process any inserts in lpMsgBuf.
|
||||
// ...
|
||||
// Display the string.
|
||||
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "MD5 AcquireContext Error", MB_OK | MB_ICONINFORMATION );
|
||||
// Free the buffer.
|
||||
LocalFree( lpMsgBuf );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CryptCreateHash(hProv,CALG_MD5, 0, 0, &Hash);
|
||||
|
||||
int input_len = lstrlen(input);
|
||||
|
||||
BYTE md5raw[2048];
|
||||
int md5raw_len = 2048;
|
||||
CryptHashData(Hash,(unsigned char*)input,input_len, 0); // md5 of "<time>:<password>"
|
||||
CryptGetHashParam(Hash, HP_HASHVAL, md5raw,(DWORD*)&md5raw_len,0);
|
||||
|
||||
wsprintf(output,""); // Make output a terminated string
|
||||
|
||||
char temp[4];
|
||||
//wsprintf(temp,"%d",md5raw_len);
|
||||
//MessageBox(NULL,temp,"gen_httpSrv md5raw_len",MB_OK);
|
||||
|
||||
for (int i=0;i<md5raw_len;i++)
|
||||
{
|
||||
wsprintf(temp,"%2.2x", md5raw[i]);
|
||||
lstrcat(output,temp);
|
||||
}
|
||||
|
||||
//MessageBox(NULL,output,"gen_httpSrv debug MD5", MB_OK);
|
||||
|
||||
|
||||
|
||||
|
||||
CryptReleaseContext(hProv,0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Sends a 401 for Basic authentication
|
||||
int SendBasic401(connection * conn, char * realm)
|
||||
{
|
||||
prints(conn,"HTTP/1.0 401 Unauthorized\nWWW-Authenticate: Basic realm=\"");
|
||||
prints(conn,realm);
|
||||
prints(conn,"\"\n");
|
||||
prints(conn,"Content-Type: text/html\n\n<html>\n<head>\n<title>Login Failed</title>\n");
|
||||
Style(conn);
|
||||
CloseHeader(conn);
|
||||
OpenPageBody(conn);
|
||||
prints(conn,"<h1>Login Failed</h1>\n<p><b>Winamp Web Interface could not log you in.</b></p>\n<p><a href=\"/main\">Back to main page</a></p>");
|
||||
CloseBody(conn);
|
||||
conn->http.responsecode = 401;
|
||||
return ST_CLOSE;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Finds a substring in another string. Probably should be in strings.cpp...
|
||||
char * FindSubString(char * buffer,char * target)
|
||||
{
|
||||
//MessageBox(NULL,buffer,"gen_httpSrv FindSubString",MB_OK);
|
||||
int len = lstrlen(buffer) - lstrlen(target);
|
||||
for (int i=0;i<=len;i++)
|
||||
{
|
||||
if (StartString(target,buffer+i))
|
||||
return (char*)(buffer+i);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Finds auth headers in a request
|
||||
void FindBasicAuth(connection * conn, char * buffer)
|
||||
{
|
||||
//int ptr;
|
||||
//MessageBox(NULL,buffer,"gen_httpSrv FindBasicAuth: buffer",MB_OK);
|
||||
char * chptr = FindSubString(buffer,"Authorization:"); // Look for auth
|
||||
if (!chptr)
|
||||
{ // Not found
|
||||
chptr = FindSubString(buffer,"Authorisation:"); // Misspellings?
|
||||
if (!chptr) // Still no; fail
|
||||
{
|
||||
//MessageBox(NULL,"No Auth","gen_httpSrv debug FindBasicAuth",MB_OK);
|
||||
conn->http.auth = CheckCredentials(conn,"anon","");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Authorisation section found
|
||||
//MessageBox(NULL,chptr,"gen_httpSrv debug",MB_OK);
|
||||
|
||||
char temp[100];
|
||||
|
||||
|
||||
char * cl_user;
|
||||
char * cl_pass;
|
||||
|
||||
chptr = GetAString(chptr,(char*)&temp); // chptr now points at Authorisation, so get it
|
||||
chptr = GetAString(chptr,(char*)&temp); // get auth mode - 'basic'
|
||||
chptr = GetAString(chptr,(char*)&temp); // get user/pass string
|
||||
|
||||
char userpass[100];
|
||||
FromBase64((char*)&temp,(char*)&userpass);
|
||||
|
||||
int i=0;
|
||||
while(userpass[i] != ':')
|
||||
{
|
||||
if (userpass[i] == 0)
|
||||
{
|
||||
conn->http.auth = CheckCredentials(conn,"anon","");
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
userpass[i] = 0;
|
||||
cl_pass = &userpass[i+1];
|
||||
cl_user = (char*)&userpass;
|
||||
|
||||
|
||||
//wsprintf(temp,"User: %s\nPassword: %s",cl_user,cl_pass);
|
||||
//MessageBox(NULL,temp,"user/password",MB_TOPMOST | MB_OK);
|
||||
//MessageBox(NULL,temp,"gen_httpSrv debug base64 from client",MB_OK);
|
||||
|
||||
conn->http.auth = CheckCredentials(conn, cl_user, cl_pass);
|
||||
|
||||
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
// Converts a string to Base64
|
||||
void ToBase64(char * instr, char * outstr)
|
||||
{
|
||||
//MessageBox(NULL,instr,"instr",MB_OK);
|
||||
|
||||
int i=0;
|
||||
int o=0;
|
||||
int j = lstrlen(instr);
|
||||
|
||||
bool done = false;
|
||||
|
||||
while(instr[i] != 0 && done == false)
|
||||
{
|
||||
outstr[o] = bchars[(instr[i] & 0xFC) / 4];
|
||||
outstr[o+1] = bchars[((instr[i] & 0x03) * 16) + ((instr[i+1] & 0xF0) / 16)];
|
||||
if (instr[i+1] == 0)
|
||||
{
|
||||
outstr[o+2] = '=';
|
||||
outstr[o+3] = '=';
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
outstr[o+2] = bchars[((instr[i+1] & 0x0F) * 4) + ((instr[i+2] & 0xC0) /64)];
|
||||
if (instr[i+2] == 0)
|
||||
{
|
||||
outstr[o+3] = '=';
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
outstr[o+3] = bchars[(instr[i+2] & 0x3F)];
|
||||
}
|
||||
|
||||
o += 4;
|
||||
i += 3;
|
||||
}
|
||||
|
||||
outstr[o] = 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Converts a Base64 string to plaintext
|
||||
void FromBase64(char * instr,char * outstr)
|
||||
{
|
||||
int i=0;
|
||||
int o=0;
|
||||
int j=lstrlen(instr);
|
||||
|
||||
for (int n=0;n<j;n++) // reduce ascii codes to numbers
|
||||
{
|
||||
if (instr[n] != '=')
|
||||
instr[n] = achars[instr[n]];
|
||||
else
|
||||
instr[n] = (char)255;
|
||||
}
|
||||
|
||||
while(instr[i] != 0)
|
||||
{
|
||||
outstr[o] = ((instr[i] & 0x3F) * 4) + ((instr[i+1] & 0x30) / 16);
|
||||
|
||||
if (instr[i+2] == (char)255)
|
||||
outstr[o+1] = 0;
|
||||
else
|
||||
{
|
||||
outstr[o+1] = ((instr[i+1] & 0x0F) * 16) + ((instr[i+2] & 0x3C) / 4);
|
||||
|
||||
if (instr[i+3] == (char)255)
|
||||
outstr[o+2] = 0;
|
||||
else
|
||||
outstr[o+2] = ((instr[i+2] & 0x03) * 64) + (instr[i+3] & 0x3F);
|
||||
}
|
||||
|
||||
i += 4;
|
||||
o += 3;
|
||||
}
|
||||
outstr[o] = 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Checks credentials with those in ini file
|
||||
int CheckCredentials(connection * conn, char * user, char * pass)
|
||||
{
|
||||
|
||||
char ini_file[MAX_PATH], *p;
|
||||
GetModuleFileName(plugin.hDllInstance,ini_file,sizeof(ini_file));
|
||||
p=ini_file+lstrlen(ini_file);
|
||||
while (p >= ini_file && *p != '\\') p--;
|
||||
if (++p >= ini_file) *p = 0;
|
||||
lstrcat(ini_file,"gen_httpsrv.ini");
|
||||
|
||||
if (StrComp(user,"anon"))
|
||||
return GetUserAccess(ini_file,user);
|
||||
|
||||
char password[40];
|
||||
|
||||
GetPrivateProfileString("Users",user,"",(char*)&password,40,ini_file);
|
||||
|
||||
char md5pass[40];
|
||||
if (securepassword == 1)
|
||||
MD5(pass,(char*)&md5pass,40);
|
||||
else
|
||||
ToBase64(pass,md5pass);
|
||||
|
||||
//if (password[0] == 0)
|
||||
// return AUTH_ANON;
|
||||
|
||||
//char temp[150];
|
||||
//wsprintf(temp,"file: %s\nrecv: %s",password,md5pass);
|
||||
//MessageBox(NULL,temp,"auth",MB_OK | MB_TOPMOST);
|
||||
|
||||
if (StrComp(password,md5pass))
|
||||
{
|
||||
wsprintf(conn->http.user,user);
|
||||
return GetUserAccess(ini_file, user);
|
||||
}
|
||||
else
|
||||
return AUTH_ANON;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Gets access rights from the ini file
|
||||
int GetUserAccess(char * ini_file,char * user)
|
||||
{
|
||||
char useraccesskey[30];
|
||||
wsprintf(useraccesskey, "#%s_access", user);
|
||||
return GetPrivateProfileInt("Users",useraccesskey,AUTH_ANON,ini_file);
|
||||
}
|
||||
Reference in New Issue
Block a user