diff --git a/BBSHTMLConfig.c b/BBSHTMLConfig.c index d328419..d1a62ce 100644 --- a/BBSHTMLConfig.c +++ b/BBSHTMLConfig.c @@ -116,7 +116,7 @@ int SendWebMailHeader(char * Reply, char * Key, struct HTTPConnectionInfo * Sess struct UserInfo * FindBBS(char * Name); void ReleaseWebMailStruct(WebMailInfo * WebMail); VOID TidyWelcomeMsg(char ** pPrompt); -int MailAPIProcessHTTPMessage(struct HTTPConnectionInfo * Session, char * response, char * Method, char * URL, char * request, BOOL LOCAL, char * Param); +int MailAPIProcessHTTPMessage(struct HTTPConnectionInfo * Session, char * response, char * Method, char * URL, char * request, BOOL LOCAL, char * Param, char * Token); char UNC[] = ""; char CHKD[] = "checked=checked "; @@ -447,7 +447,7 @@ void ConvertTitletoUTF8(WebMailInfo * WebMail, char * Title, char * UTF8Title, i BOOL GotFirstMessage = 0; -void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen) +void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen, char * Token) { char * Context = 0, * NodeURL; int ReplyLen; @@ -480,7 +480,7 @@ void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, if (_memicmp(URL, "/Mail/API/v1/", 13) == 0) { - *RLen = MailAPIProcessHTTPMessage(Session, Reply, Method, URL, input, LOCAL, Context); + *RLen = MailAPIProcessHTTPMessage(Session, Reply, Method, URL, input, LOCAL, Context, Token); return; } @@ -2997,6 +2997,8 @@ int ProcessWebmailWebSock(char * MsgPtr, char * OutBuffer); static char PipeFileName[] = "\\\\.\\pipe\\BPQMailWebPipe"; +// Constants + static DWORD WINAPI InstanceThread(LPVOID lpvParam) // This routine is a thread processing function to read from and reply to a client @@ -3017,6 +3019,7 @@ static DWORD WINAPI InstanceThread(LPVOID lpvParam) char URL[100001]; char * Context, * Method; int n; + char token[16]= ""; char * ptr; @@ -3052,18 +3055,43 @@ static DWORD WINAPI InstanceThread(LPVOID lpvParam) } else { - strcpy(URL, MsgPtr); + // look for auth header + + const char * auth_header = "Authorization: Bearer "; + char * token_begin = strstr(MsgPtr, auth_header); + int Flags = 0, n; - ptr = strstr(URL, " HTTP"); + // Node Flags isn't currently used - if (ptr) - *ptr = 0; + char * Tok; + char * param; - Method = strtok_s(URL, " ", &Context); + if (token_begin) + { + // Using Auth Header + + // Extract the token from the request (assuming it's present in the request headers) - ProcessMailHTTPMessage(&Session, Method, Context, MsgPtr, OutBuffer, &OutputLen, InputLen); + token_begin += strlen(auth_header); // Move to the beginning of the token + strncpy(token, token_begin, 13); + token[13] = '\0'; // Null-terminate the token + } } + strcpy(URL, MsgPtr); + + + + ptr = strstr(URL, " HTTP"); + + if (ptr) + *ptr = 0; + + Method = strtok_s(URL, " ", &Context); + + ProcessMailHTTPMessage(&Session, Method, Context, MsgPtr, OutBuffer, &OutputLen, InputLen, token); + + WriteFile(hPipe, &Session, sizeof (struct HTTPConnectionInfo), &n, NULL); WriteFile(hPipe, OutBuffer, OutputLen, &cbWritten, NULL); diff --git a/BBSUtilities.c b/BBSUtilities.c index 1db4bed..06feafc 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -8136,6 +8136,15 @@ BOOL ProcessBBSConnectScript(CIRCUIT * conn, char * Buffer, int len) Line = Scripts[n]; } + if (Line == NULL) + { + // No more lines - Disconnect + + conn->BBSFlags &= ~RunningConnectScript; // so it doesn't get reentered + Disconnect(conn->BPQStream); + return FALSE; + } + if (_memicmp(Line, "TIMES", 5) == 0) { NextBand: diff --git a/HTTPcode.c b/HTTPcode.c index 14ed523..284170e 100644 --- a/HTTPcode.c +++ b/HTTPcode.c @@ -106,7 +106,7 @@ char * strlop(char * buf, char delim); VOID sendandcheck(SOCKET sock, const char * Buffer, int Len); int CompareNode(const void *a, const void *b); int CompareAlias(const void *a, const void *b); -void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen); +void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen, char * Token); void ProcessChatHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen); struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); int SetupNodeMenu(char * Buff, int SYSOP); @@ -2123,11 +2123,7 @@ Returnit: Compressed = Reply; if (NodeURL && _memicmp(NodeURL, "/mail/api/", 10) == 0) - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\n" - "Content-Length: %d\r\n" - "Content-Type: application/json\r\n" - "Connection: close\r\n" - "%s\r\n", ReplyLen, Encoding); + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: application/json\r\nConnection: close\r\n%s\r\n", ReplyLen, Encoding); else HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n%s\r\n", ReplyLen, Encoding); @@ -2150,6 +2146,27 @@ doHeader: char _REPLYBUFFER[250000]; struct HTTPConnectionInfo Dummy = {0}; int Sent, Loops = 0; + char token[16] = ""; + + // look for auth header + + const char * auth_header = "Authorization: Bearer "; + char * token_begin = strstr(MsgPtr, auth_header); + int Flags = 0, n; + + char * Tok; + char * param; + + if (token_begin) + { + // Using Auth Header + + // Extract the token from the request (assuming it's present in the request headers) + + token_begin += strlen(auth_header); // Move to the beginning of the token + strncpy(token, token_begin, 13); + token[13] = '\0'; // Null-terminate the token + } ReplyLen = 0; @@ -2161,7 +2178,7 @@ doHeader: else Session->TNC = (void *)0; - ProcessMailHTTPMessage(Session, Method, Context, MsgPtr, _REPLYBUFFER, &ReplyLen, MsgLen); + ProcessMailHTTPMessage(Session, Method, Context, MsgPtr, _REPLYBUFFER, &ReplyLen, MsgLen, token); if (Context && _memicmp(Context, "/mail/api/", 10) == 0) { @@ -2171,9 +2188,9 @@ doHeader: if (allowDeflate) Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); else - Compressed = Reply; + Compressed = _REPLYBUFFER; - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n%s\r\n", ReplyLen, Encoding); + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: application/json\r\nConnection: close\r\n%s\r\n", ReplyLen, Encoding); sendandcheck(sock, Header, HeaderLen); sendandcheck(sock, Compressed, ReplyLen); @@ -2306,6 +2323,8 @@ doHeader: // Pass to MailChat if active + NodeURL = Context; + if ((_memicmp(Context, "/MAIL/", 6) == 0) || (_memicmp(Context, "/WebMail", 8) == 0)) { // If for Mail, Pass to Mail Server via Named Pipe @@ -4248,42 +4267,53 @@ int ProcessMailAPISignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char int i; struct UserRec * USER; - user = strlop(MsgPtr, '?'); - password = strlop(user, '&'); - strlop(password, ' '); - - - for (i = 0; i < TCP->NumberofUsers; i++) + if (strchr(MsgPtr, '?')) { - USER = TCP->UserRecPtr[i]; + // Check Password + + user = strlop(MsgPtr, '?'); + password = strlop(user, '&'); + strlop(password, ' '); - if (user && _stricmp(user, USER->UserName) == 0) + for (i = 0; i < TCP->NumberofUsers; i++) { - if ((strcmp(password, USER->Password) == 0) && (USER->Secure || WebMail)) + USER = TCP->UserRecPtr[i]; + + if (user && _stricmp(user, USER->UserName) == 0) { - // ok + if ((strcmp(password, USER->Password) == 0) && (USER->Secure || WebMail)) + { + // ok - NewSession = AllocateSession(Appl[0], 'M'); + NewSession = AllocateSession(Appl[0], 'M'); - *Session = NewSession; + *Session = NewSession; + + if (NewSession) + { + ReplyLen = 0; + strcpy(NewSession->Callsign, USER->Callsign); + } + else + { + ReplyLen = SetupNodeMenu(Reply, LOCAL); + ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); + } + return ReplyLen; - if (NewSession) - { - ReplyLen = 0; - strcpy(NewSession->Callsign, USER->Callsign); - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); } - return ReplyLen; - } } - } - // Pass failed attempt to BBS code so it can try a bbs user login + // Pass failed attempt to BBS code so it can try a bbs user login + + // Need to put url back together + + if (user && user[0] && password && password[0]) + { + sprintf(MsgPtr, "%s?%s&%s", MsgPtr, user, password); + } + } NewSession = AllocateSession(Appl[0], 'M'); diff --git a/mailapi.c b/mailapi.c index 44de32c..f447e7b 100644 --- a/mailapi.c +++ b/mailapi.c @@ -1,6 +1,6 @@ // basic JASON API to BPQ Node -// Authentication is via Telnet USER records. +// Authentication is via Telnet USER records or bbs records #define _CRT_SECURE_NO_DEPRECATE @@ -62,9 +62,9 @@ int sendFwdConfig(struct HTTPConnectionInfo * Session, char * response, char * R static struct MailAPI APIList[] = { - "/mail/api/v1/msgs", 17, sendMsgList, AuthBBSUser | AuthSysop, - "/mail/api/v1/FwdQLen", 20, sendFwdQueueLen, AuthBBSUser | AuthSysop, - "/mail/api/v1/FwdConfig", 22, sendFwdConfig, AuthBBSUser | AuthSysop, + "/mail/api/v1/msgs", 17, sendMsgList, 0, + "/mail/api/v1/FwdQLen", 20, sendFwdQueueLen, AuthSysop, + "/mail/api/v1/FwdConfig", 22, sendFwdConfig, AuthSysop, }; static int APICount = sizeof(APIList) / sizeof(struct MailAPI); @@ -152,29 +152,6 @@ static void add_token_to_list(MailToken * token) } } -static int verify_token(const char* token) -{ - // Find the token in the token list - MailToken * existing_token = find_token(token); - - if (existing_token != NULL) - { - // Check if the token has expired - time_t current_time = time(NULL); - if (current_time > existing_token->expiration_time) - { - // Token has expired, remove it from the token list - remove_expired_tokens(); - return 0; - } - // Token is valid - return 1; - } - - // Token doesn't exist in the token list - return 0; -} - static void remove_expired_tokens() { time_t current_time = time(NULL); @@ -206,6 +183,7 @@ static void remove_expired_tokens() static MailToken * find_token(const char* token) { MailToken * current_token = token_list; + while (current_token != NULL) { if (strcmp(current_token->token, token) == 0) @@ -223,7 +201,7 @@ static int send_http_response(char * response, const char* msg) } -int MailAPIProcessHTTPMessage(struct HTTPConnectionInfo * Session, char * response, char * Method, char * URL, char * request, BOOL LOCAL, char *Params) +int MailAPIProcessHTTPMessage(struct HTTPConnectionInfo * Session, char * response, char * Method, char * URL, char * request, BOOL LOCAL, char *Params, char * TokenString) { char * pass = strlop(Params, '&'); int Flags = 0, n; @@ -261,6 +239,11 @@ int MailAPIProcessHTTPMessage(struct HTTPConnectionInfo * Session, char * respon strcpy(Session->Callsign, User->Call); Auth = AuthBBSUser; + if (User->flags & F_SYSOP) + Auth |= AuthSysop; + + + } } else @@ -295,6 +278,29 @@ int MailAPIProcessHTTPMessage(struct HTTPConnectionInfo * Session, char * respon return strlen(response); } + // Find Token + + if (TokenString[0]) // Token form Auth Header + Token = find_token(TokenString); + else + Token = find_token(Params); // Token form URL + + if (Token != NULL) + { + // Check if the token has expired + + time_t current_time = time(NULL); + if (current_time > Token->expiration_time) + { + // Token has expired, remove it from the token list + remove_expired_tokens(); + Token = NULL; + } + } + + if (Token) + Auth |= Token->Auth; + // Determine the requested API endpoint for (n = 0; n < APICount; n++) @@ -329,6 +335,9 @@ int MailAPIProcessHTTPMessage(struct HTTPConnectionInfo * Session, char * respon if (APIEntry->Auth) { // Check Level + + if ((Auth & APIEntry->Auth) == 0) + return send_http_response(response, "403 (Not Authorized)"); } if (rest[0] == ' ' || rest[0] == '/' || rest[0] == '?')