From 3e2574333cf5861461a1ca1b6a02200fdabdfce6 Mon Sep 17 00:00:00 2001 From: Colum Paget Date: Tue, 29 Oct 2024 10:09:49 +0000 Subject: [PATCH] v5.30: fix TerminalTextAlign, work on HttpServer and PasswordFile --- CHANGELOG | 6 +++++ Encodings.c | 52 +++++++++++++++++------------------ Errors.h | 12 ++++++++- Http.c | 34 ++++++++++++++++------- HttpServer.c | 48 ++++++++++++++++++++++++++------- HttpServer.h | 3 +++ Makefile | 4 +-- Makefile.in | 4 +-- PasswordFile.c | 27 +++++++++++++------ PasswordFile.h | 6 ++--- Seccomp.c | 66 ++++++++++++++++++++++----------------------- Server.c | 5 ++-- SpawnPrograms.c | 4 +-- Stream.c | 4 +-- StreamAuth.c | 12 ++++----- Terminal.c | 6 +++++ examples/uudecode.c | 18 +++++++++++++ 17 files changed, 204 insertions(+), 107 deletions(-) create mode 100644 examples/uudecode.c diff --git a/CHANGELOG b/CHANGELOG index 8114048..9b34f52 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +v5.30 (2024-10-29) + * Fix crash if TerminalTextAlign has NULL for the Terminal + * Added HttpGet and HttpPost functions + * Improvements to httpserver authentication. + * Add 'extra' field to passwords file to allow storing data against a user. + v5.29 (2024-10-29) * much more seccomp work * add 'data' option to pty config (PtyParseConfig) so if a pipe or pty is going to be used for raw data transfer, use FLUSH_ALWAYS not FLUSH_LINE diff --git a/Encodings.c b/Encodings.c index 6c59af9..aa10de7 100644 --- a/Encodings.c +++ b/Encodings.c @@ -14,8 +14,8 @@ char *EncodeQuoted(char *Return, const char *Input, int len, char QuoteChar) { if ( (*ptr < 32) || (*ptr > 127) || (*ptr == '=') ) { - snprintf(Hex, 3, "%02x", (*ptr) & 0xFF); - Return=MCatStr(Return, "=", Hex, NULL); + snprintf(Hex, 3, "%02x", (*ptr) & 0xFF); + Return=MCatStr(Return, "=", Hex, NULL); } else Return=AddCharToStr(Return, *ptr); } @@ -43,16 +43,16 @@ int DecodeQuoted(char **Return, const char *Text, char QuoteChar) { strncpy(Hex, ptr, 2); *Return=AddCharToBuffer(*Return, len, strtol(Hex, NULL, 16)); - len++; + len++; ptr++; if (*ptr=='\0') break; } } - else - { - *Return=AddCharToBuffer(*Return, len, *ptr); - len++; - } + else + { + *Return=AddCharToBuffer(*Return, len, *ptr); + len++; + } } return(len); @@ -63,18 +63,18 @@ int DecodeQuoted(char **Return, const char *Text, char QuoteChar) char *EncodeYenc(char *Return, const char *Input, int len, char QuoteChar) { const char *ptr; - char echar; + char echar; for (ptr=Input; ptr < (Input + len); ptr++) { - //shift the character up some bytes, because the null byte is a common occurance - //in binary files, and we don't want to escape it, increasing the size of the - //file. We'll escape some less common byte in it's place - echar = (*ptr + 42) % 256; //of course it's 42 + //shift the character up some bytes, because the null byte is a common occurance + //in binary files, and we don't want to escape it, increasing the size of the + //file. We'll escape some less common byte in it's place + echar = (*ptr + 42) % 256; //of course it's 42 if ( (echar==0) || (echar=='\r') || (echar=='\n') || (echar==QuoteChar)) { - Return=AddCharToStr(Return, QuoteChar); - Return=AddCharToStr(Return, (echar + 62) % 256); + Return=AddCharToStr(Return, QuoteChar); + Return=AddCharToStr(Return, (echar + 62) % 256); } else Return=AddCharToStr(Return, echar); } @@ -94,12 +94,12 @@ int DecodeYenc(char **Return, const char *Text, char QuoteChar) { ptr++; if (*ptr=='\0') break; - echar=*ptr - 62; + echar=*ptr - 62; } else echar=*ptr; - - *Return=AddCharToBuffer(*Return, len, echar - 42); - len++; + + *Return=AddCharToBuffer(*Return, len, echar - 42); + len++; } return(len); @@ -231,11 +231,11 @@ int EncodingParse(const char *Str) else if (strcasecmp(Str,"xxenc")==0) Encode=ENCODE_XXENC; break; - case 'y': - case 'Y': + case 'y': + case 'Y': if (strcasecmp(Str,"yenc")==0) Encode=ENCODE_YENCODE; else if (strcasecmp(Str,"yencode")==0) Encode=ENCODE_YENCODE; - break; + break; case 'z': case 'Z': @@ -309,12 +309,12 @@ char *EncodeBytes(char *Buffer, const char *Bytes, int len, int Encoding) switch (Encoding) { case ENCODE_QUOTED_MIME: - RetStr=EncodeQuoted(RetStr, Bytes, len, '='); - break; + RetStr=EncodeQuoted(RetStr, Bytes, len, '='); + break; case ENCODE_YENCODE: - RetStr=EncodeYenc(RetStr, Bytes, len, '='); - break; + RetStr=EncodeYenc(RetStr, Bytes, len, '='); + break; case ENCODE_BASE32: RetStr=base32encode(RetStr, Bytes, len, BASE32_RFC4648_CHARS, '='); diff --git a/Errors.h b/Errors.h index 41e9893..63e12a9 100644 --- a/Errors.h +++ b/Errors.h @@ -54,6 +54,16 @@ Errors are injected into the list with RaiseError like this: ListUsefulSetValue("Error:notty","Y") + If the ERRFLAG_SYSLOG flag is passed, like this: + + RaiseError(ERRFLAG_ERRNO|ERRFLAG_SYSLOG, "ServiceConnect", "host=%s port=%d",Host, Port); + + Then the error will be logged to the system logger. Alternatively if the LibUseful value 'Error:Syslog' is set, like this: + + ListUsefulSetValue("Error:Syslog","Y") + + then all error and debug messages are sent to the system logger via syslog. + If the flag ERRFLAG_DEBUG is set then RaiseError won't print anything out by default. So this line: RaiseError(ERRFLAG_DEBUG, "ServiceConnect", "host=%s port=%d",Host, Port); @@ -70,7 +80,6 @@ Errors are injected into the list with RaiseError like this: If the libUseful internal value 'Error:Silent' is set true/yes/y with ListUsefulSetValue then RaiseError never prints errors to stderr, regardless of any other config. - If the value 'Error:Syslog' is set true/yes/y then error and debug messages are sent to the system logger via syslog */ @@ -90,6 +99,7 @@ extern "C" { #endif +//call 'RaiseError' to add an error into the error sytem #define RaiseError(flags, where, fmt, ...) InternalRaiseError(flags, where, __FILE__, __LINE__, fmt, ##__VA_ARGS__) //clears the list of errors diff --git a/Http.c b/Http.c index eec31f3..87b591d 100644 --- a/Http.c +++ b/Http.c @@ -1244,21 +1244,37 @@ STREAM *HTTPWithConfig(const char *URL, const char *Config) + +int HTTPCopyToSTREAM(STREAM *Con, STREAM *S) +{ + const char *ptr; + size_t size=0; + + //do not check response code of HTTP server streams (strictly speaking STREAM_TYPE_HTTP_ACCEPT) + if (S->Type == STREAM_TYPE_HTTP) + { + ptr=STREAMGetValue(Con, "HTTP:ResponseCode"); + if ((! ptr) || (*ptr !='2')) + { + STREAMClose(Con); + return(-1); + } + } + + ptr=STREAMGetValue(Con, "HTTP:Content-Length"); + if (StrValid(ptr)) size=strtol(ptr, NULL, 10); + + return(STREAMSendFile(Con, S, size, SENDFILE_LOOP)); +} + + int HTTPDownload(char *URL, STREAM *S) { STREAM *Con; - const char *ptr; Con=HTTPGet(URL); if (! Con) return(-1); - - ptr=STREAMGetValue(Con, "HTTP:ResponseCode"); - if ((! ptr) || (*ptr !='2')) - { - STREAMClose(Con); - return(-1); - } - return(STREAMSendFile(Con, S, 0, SENDFILE_LOOP)); + return(HTTPCopyToSTREAM(Con, S)); } diff --git a/HttpServer.c b/HttpServer.c index a007df4..e970e24 100644 --- a/HttpServer.c +++ b/HttpServer.c @@ -11,6 +11,7 @@ static void HTTPServerSetValue(STREAM *S, const char *Name, const char *Value) //do not allow these to be set, as they will //overwrite the true HTTP method and url + if (strcmp(Name, "HTTP-Version")==0) return; if (strcmp(Name, "Method")==0) return; if (strcmp(Name, "URL")==0) return; @@ -48,7 +49,7 @@ void HTTPServerParseClientCookies(ListNode *Vars, const char *Str) void HTTPServerParseAuthorization(ListNode *Vars, const char *Str) { - char *Token=NULL; + char *Token=NULL, *Tempstr=NULL, *User=NULL, *Password=NULL; const char *ptr; ptr=Str; @@ -58,15 +59,20 @@ void HTTPServerParseAuthorization(ListNode *Vars, const char *Str) if (strcasecmp(Token, "basic")==0) { ptr=GetToken(ptr, "\\S", &Token, 0); - SetVar(Vars, "Auth:Basic", Token); + HTTPDecodeBasicAuth(Token, &User, &Password); + SetVar(Vars, "AUTH:User", User); + SetVar(Vars, "AUTH:Password", Password); } else if (strcasecmp(Token, "bearer")==0) { ptr=GetToken(ptr, "\\S", &Token, 0); - SetVar(Vars, "Auth:Bearer", Token); + SetVar(Vars, "AUTH:Bearer", Token); } + Destroy(Tempstr); Destroy(Token); + Destroy(User); + Destroy(Password); } @@ -79,7 +85,9 @@ void HTTPServerParseClientHeaders(STREAM *S) StripTrailingWhitespace(Tempstr); ptr=GetToken(Tempstr, "\\S", &Token, 0); STREAMSetValue(S, "HTTP:Method", Token); - STREAMSetValue(S, "HTTP:URL", ptr); + ptr=GetToken(ptr, "\\S", &Token, 0); + STREAMSetValue(S, "HTTP:URL", Token); + STREAMSetValue(S, "HTTP:HTTP-Version", ptr); Tempstr=STREAMReadLine(Tempstr, S); while (Tempstr) @@ -89,10 +97,13 @@ void HTTPServerParseClientHeaders(STREAM *S) ptr=GetToken(Tempstr, ":", &Token, 0); StripTrailingWhitespace(Token); - if (strcasecmp(Token, "Cookie:")==0) HTTPServerParseClientCookies(S->Values, ptr); + while (isspace(*ptr)) ptr++; + + if (strcasecmp(Token, "Cookie")==0) HTTPServerParseClientCookies(S->Values, ptr); else if (strcasecmp(Token, "Authorization")==0) HTTPServerParseAuthorization(S->Values, ptr); else if (strcasecmp(Token, "Sec-Websocket-Key") == 0) STREAMSetValue(S, "WEBSOCKET:KEY", ptr); else if (strcasecmp(Token, "Sec-Websocket-Protocol") == 0) STREAMSetValue(S, "WEBSOCKET:PROTOCOL", ptr); + //HTTPServerSetValue will ignore Method, URL and HTTP-Version so they can't be overridden by extra headers else HTTPServerSetValue(S, Token, ptr); Tempstr=STREAMReadLine(Tempstr, S); @@ -106,6 +117,7 @@ void HTTPServerParseClientHeaders(STREAM *S) void HTTPServerAccept(STREAM *S) { HTTPServerParseClientHeaders(S); + STREAMAuth(S); } @@ -145,18 +157,36 @@ void HTTPServerSendHeaders(STREAM *S, int ResponseCode, const char *ResponseText Destroy(Hash); } - -int HTTPServerSendDocument(STREAM *S, const char *Bytes, int Length, const char *ContentType, const char *Headers) +int HTTPServerSendResponse(STREAM *S, const char *ResponseCode, const char *ResponseReason, const char *Content, int Length, const char *ContentType, const char *Headers) { char *Tempstr=NULL; int result; Tempstr=FormatStr(Tempstr, "Content-Length=%d ", Length); if (StrValid(ContentType)) Tempstr=MCatStr(Tempstr, "Content-Type=", ContentType, " ", Headers, NULL); - HTTPServerSendHeaders(S, 200, "OKAY", Tempstr); - result=STREAMWriteBytes(S, Bytes, Length); + HTTPServerSendHeaders(S, atoi(ResponseCode), ResponseReason, Tempstr); + result=STREAMWriteBytes(S, Content, Length); + + Destroy(Tempstr); + return(result); +} + + +int HTTPServerSendDocument(STREAM *S, const char *Content, int Length, const char *ContentType, const char *Headers) +{ + return(HTTPServerSendResponse(S, "200", "OKAY", Content, Length, ContentType, Headers)); +} + +int HTTPServerSendStatus(STREAM *S, const char *StatusCode, const char *StatusReason) +{ + char *Tempstr=NULL; + int result; + + Tempstr=FormatStr(Tempstr, "

%s - %s

\r\n", StatusCode, StatusReason); + result=HTTPServerSendResponse(S, StatusCode, StatusReason, Tempstr, StrLen(Tempstr), "text/html", ""); Destroy(Tempstr); + return(result); } diff --git a/HttpServer.h b/HttpServer.h index c093f48..58dddf3 100644 --- a/HttpServer.h +++ b/HttpServer.h @@ -79,6 +79,9 @@ void HTTPServerParseClientHeaders(STREAM *S); void HTTPServerSendHeaders(STREAM *S, int ResponseCode, const char *ResponseText, const char *Headers); void HTTPServerAccept(STREAM *S); +int HTTPServerSendResponse(STREAM *S, const char *ResponseCode, const char *ResponseReason, const char *Content, int Length, const char *ContentType, const char *Headers); +int HTTPServerSendDocument(STREAM *S, const char *Content, int Length, const char *ContentType, const char *Headers); +int HTTPServerSendStatus(STREAM *S, const char *ErrorCode, const char *ErrorReason); int HTTPServerSendDocument(STREAM *S, const char *Bytes, int Length, const char *ContentType, const char *Headers); int HTTPServerSendFile(STREAM *S, const char *Path, const char *ContentType, const char *Headers); diff --git a/Makefile b/Makefile index 5130727..ed1161c 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = gcc -VERSION = 5.29 +VERSION = 5.30 MAJOR=5 LIBFILE=libUseful.so.$(VERSION) SONAME=libUseful.so.$(MAJOR) @@ -270,7 +270,7 @@ LibSettings.o: LibSettings.h LibSettings.c $(CC) $(FLAGS) -c LibSettings.c clean: - -rm -f *.o *.so *.so.* *.a *.orig .*.swp + -rm -f *.o *.so *.so.* *.a *.orig .*.swp *~ -rm config.log config.status -rm -r autom4te.cache config.cache -$(MAKE) clean -C examples diff --git a/Makefile.in b/Makefile.in index b78ed17..5437f46 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,5 +1,5 @@ CC = @CC@ -VERSION = 5.29 +VERSION = 5.30 MAJOR=5 LIBFILE=libUseful.so.$(VERSION) SONAME=libUseful.so.$(MAJOR) @@ -270,7 +270,7 @@ LibSettings.o: LibSettings.h LibSettings.c $(CC) $(FLAGS) -c LibSettings.c clean: - -rm -f *.o *.so *.so.* *.a *.orig .*.swp + -rm -f *.o *.so *.so.* *.a *.orig .*.swp *~ -rm config.log config.status -rm -r autom4te.cache config.cache -$(MAKE) clean -C examples diff --git a/PasswordFile.c b/PasswordFile.c index e911fef..d7ec79a 100644 --- a/PasswordFile.c +++ b/PasswordFile.c @@ -4,7 +4,7 @@ -char *PasswordFileGenerateEntry(char *RetStr, const char *User, const char *PassType, const char *Password) +char *PasswordFileGenerateEntry(char *RetStr, const char *User, const char *PassType, const char *Password, const char *Extra) { char *Salt=NULL, *Hash=NULL, *Tempstr=NULL; @@ -20,7 +20,8 @@ char *PasswordFileGenerateEntry(char *RetStr, const char *User, const char *Pass HashBytes(&Hash, PassType, Tempstr, StrLen(Tempstr), ENCODE_BASE64); } - RetStr=MCopyStr(RetStr, User, ":", PassType, ":", Salt, ":", Hash, "\n", NULL); + Tempstr=QuoteCharsInStr(Tempstr, Extra, ":"); + RetStr=MCopyStr(RetStr, User, ":", PassType, ":", Salt, ":", Hash, ":", Tempstr, "\n", NULL); Destroy(Tempstr); Destroy(Hash); @@ -30,7 +31,7 @@ char *PasswordFileGenerateEntry(char *RetStr, const char *User, const char *Pass } -int PasswordFileAdd(const char *Path, const char *PassType, const char *User, const char *Password) +int PasswordFileAdd(const char *Path, const char *PassType, const char *User, const char *Password, const char *Extra) { STREAM *Old, *New; char *Tempstr=NULL, *Token=NULL, *Salt=NULL; @@ -55,7 +56,7 @@ int PasswordFileAdd(const char *Path, const char *PassType, const char *User, co } - Tempstr=PasswordFileGenerateEntry(Tempstr, User, PassType, Password); + Tempstr=PasswordFileGenerateEntry(Tempstr, User, PassType, Password, Extra); STREAMWriteLine(Tempstr, New); rename(New->Path, Path); @@ -73,7 +74,7 @@ int PasswordFileAdd(const char *Path, const char *PassType, const char *User, co } -int PasswordFileAppend(const char *Path, const char *PassType, const char *User, const char *Password) +int PasswordFileAppend(const char *Path, const char *PassType, const char *User, const char *Password, const char *Extra) { STREAM *F; char *Tempstr=NULL, *Token=NULL; @@ -83,7 +84,7 @@ int PasswordFileAppend(const char *Path, const char *PassType, const char *User, if (! F) return(FALSE); STREAMSeek(F, 0, SEEK_END); - Tempstr=PasswordFileGenerateEntry(Tempstr, User, PassType, Password); + Tempstr=PasswordFileGenerateEntry(Tempstr, User, PassType, Password, Extra); STREAMWriteLine(Tempstr, F); STREAMClose(F); @@ -128,10 +129,11 @@ static int PasswordFileMatchItem(const char *Data, const char *User, const char } -int PasswordFileCheck(const char *Path, const char *User, const char *Password) +int PasswordFileCheck(const char *Path, const char *User, const char *Password, char **Extra) { STREAM *F; char *Tempstr=NULL; + const char *ptr; int result=FALSE; F=STREAMOpen(Path, "r"); @@ -142,7 +144,16 @@ int PasswordFileCheck(const char *Path, const char *User, const char *Password) { StripTrailingWhitespace(Tempstr); result=PasswordFileMatchItem(Tempstr, User, Password); - if (result) break; + if (result) + { + if (Extra) + { + ptr=strrchr(Tempstr, ':'); + *Extra=UnQuoteStr(*Extra, ptr+1); + } + break; + } + Tempstr=STREAMReadLine(Tempstr, F); } diff --git a/PasswordFile.h b/PasswordFile.h index 778a37b..72417cd 100644 --- a/PasswordFile.h +++ b/PasswordFile.h @@ -28,14 +28,14 @@ extern "C" { // to remove previous entries, this function builds an new password file, and then atomically moves // it into place to replace the existing one. It will not remove any duplicate entries for other // users. -int PasswordFileAdd(const char *Path, const char *PassType, const char *User, const char *Password); +int PasswordFileAdd(const char *Path, const char *PassType, const char *User, const char *Password, const char *Extra); // Add an entry to the password file, not replacing previous entries, to previous passwords can still be // used. This does not require rebuilding the file, and thus may be more efficient than PasswordFileAdd -int PasswordFileAppend(const char *Path, const char *PassType, const char *User, const char *Password); +int PasswordFileAppend(const char *Path, const char *PassType, const char *User, const char *Password, const char *Extra); //check a users password matches the one stored in password file at 'Path' -int PasswordFileCheck(const char *Path, const char *User, const char *Password); +int PasswordFileCheck(const char *Path, const char *User, const char *Password, char **ReturnedData); #ifdef __cplusplus } diff --git a/Seccomp.c b/Seccomp.c index b8f1f69..2aa1890 100644 --- a/Seccomp.c +++ b/Seccomp.c @@ -11,9 +11,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include //for offsetof macro static int InstructionCount=0; @@ -649,8 +649,8 @@ int SeccompFilterAddSyscall(struct sock_filter **Filt, int SysCall, const char * break; } } - else RaiseError(0, "SeccompFilterAddSyscall","ERROR: BadArgument %d to syscall %d", argcount, SysCall); - argcount++; + else RaiseError(0, "SeccompFilterAddSyscall","ERROR: BadArgument %d to syscall %d", argcount, SysCall); + argcount++; ptr=GetArg(ptr, &pos, &type, &value); } @@ -680,7 +680,7 @@ static int SeccompCommit(struct sock_filter **Filt, int Action) if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &SeccompProg)) { - RaiseError(ERRFLAG_ERRNO, "SeccompCommit","ERROR: prctl(PR_SET_SECCOMP) failed "); + RaiseError(ERRFLAG_ERRNO, "SeccompCommit","ERROR: prctl(PR_SET_SECCOMP) failed "); return(FALSE); } @@ -706,15 +706,15 @@ static int LookupSocketFamily(const char *name) //equals something, or "2b" to check a bit within the second argument static int SeccompAddCheck(char **Args, const char *Fmt, int Value) { -int ArgInt; -char *Tempstr=NULL; + int ArgInt; + char *Tempstr=NULL; - ArgInt=Value; - Tempstr=FormatStr(Tempstr, Fmt, ArgInt); - *Args=MCatStr(*Args, Tempstr, " ", NULL); + ArgInt=Value; + Tempstr=FormatStr(Tempstr, Fmt, ArgInt); + *Args=MCatStr(*Args, Tempstr, " ", NULL); -Destroy(Tempstr); -return(ArgInt); + Destroy(Tempstr); + return(ArgInt); } static int SeccompParseArg0(int SyscallID, const char *Name, char **Args) @@ -801,11 +801,11 @@ static int SeccompParseArg0(int SyscallID, const char *Name, char **Args) if (strcasecmp(Name, "create")==0) SeccompAddCheck(Args, "1b%d", O_CREAT); if (strcasecmp(Name, "write")==0) SeccompAddCheck(Args, "1b%d", O_CREAT | O_WRONLY | O_RDWR | O_APPEND); if (strcasecmp(Name, "suid")==0) SeccompAddCheck(Args, "2b%d", S_ISUID | S_ISGID); - if (strcasecmp(Name, "exec")==0) - { - SeccompAddCheck(Args, "1b%d", O_CREAT); - SeccompAddCheck(Args, "2b%d", S_IXUSR | S_IXGRP | S_IXOTH); - } + if (strcasecmp(Name, "exec")==0) + { + SeccompAddCheck(Args, "1b%d", O_CREAT); + SeccompAddCheck(Args, "2b%d", S_IXUSR | S_IXGRP | S_IXOTH); + } break; #endif @@ -814,11 +814,11 @@ static int SeccompParseArg0(int SyscallID, const char *Name, char **Args) if (strcasecmp(Name, "create")==0) SeccompAddCheck(Args, "1b%d", O_CREAT); if (strcasecmp(Name, "write")==0) SeccompAddCheck(Args, "1b%d", O_CREAT | O_WRONLY | O_RDWR | O_APPEND); if (strcasecmp(Name, "suid")==0) SeccompAddCheck(Args, "2b%d", S_ISUID | S_ISGID); - if (strcasecmp(Name, "exec")==0) - { - SeccompAddCheck(Args, "1b%d", O_CREAT); - SeccompAddCheck(Args, "2b%d", S_IXUSR | S_IXGRP | S_IXOTH); - } + if (strcasecmp(Name, "exec")==0) + { + SeccompAddCheck(Args, "1b%d", O_CREAT); + SeccompAddCheck(Args, "2b%d", S_IXUSR | S_IXGRP | S_IXOTH); + } break; #endif @@ -828,11 +828,11 @@ static int SeccompParseArg0(int SyscallID, const char *Name, char **Args) if (strcasecmp(Name, "create")==0) SeccompAddCheck(Args, "2b%d", O_CREAT); if (strcasecmp(Name, "write")==0) SeccompAddCheck(Args, "2b%d", O_CREAT | O_WRONLY | O_RDWR | O_APPEND); if (strcasecmp(Name, "suid")==0) SeccompAddCheck(Args, "3b%d", S_ISUID | S_ISGID); - if (strcasecmp(Name, "exec")==0) - { - SeccompAddCheck(Args, "2b%d", O_CREAT); - SeccompAddCheck(Args, "3b%d", S_IXUSR | S_IXGRP | S_IXOTH); - } + if (strcasecmp(Name, "exec")==0) + { + SeccompAddCheck(Args, "2b%d", O_CREAT); + SeccompAddCheck(Args, "3b%d", S_IXUSR | S_IXGRP | S_IXOTH); + } break; #endif @@ -841,11 +841,11 @@ static int SeccompParseArg0(int SyscallID, const char *Name, char **Args) if (strcasecmp(Name, "create")==0) SeccompAddCheck(Args, "2b%d", O_CREAT); if (strcasecmp(Name, "write")==0) SeccompAddCheck(Args, "2b%d", O_CREAT | O_WRONLY | O_RDWR | O_APPEND); if (strcasecmp(Name, "suid")==0) SeccompAddCheck(Args, "3b%d", S_ISUID | S_ISGID); - if (strcasecmp(Name, "exec")==0) - { - SeccompAddCheck(Args, "2b%d", O_CREAT); - SeccompAddCheck(Args, "3b%d", S_IXUSR | S_IXGRP | S_IXOTH); - } + if (strcasecmp(Name, "exec")==0) + { + SeccompAddCheck(Args, "2b%d", O_CREAT); + SeccompAddCheck(Args, "3b%d", S_IXUSR | S_IXGRP | S_IXOTH); + } break; #endif diff --git a/Server.c b/Server.c index 6d5c4f8..5ecf713 100644 --- a/Server.c +++ b/Server.c @@ -115,9 +115,8 @@ static void STREAMServerParseConfig(STREAM *S, const char *Config) ptr=GetNameValuePair(Config, "\\S", "=", &Name, &Value); while (ptr) { - if (strncasecmp(Name, "SSL:", 4)==0) STREAMSetValue(S, Name, Value); - else if (strcasecmp(Name, "Authentication")==0) STREAMSetValue(S, "Authenticator", Value); - else if (strcasecmp(Name, "Auth")==0) STREAMSetValue(S, "Authenticator", Value); + if (strcasecmp(Name, "Auth")==0) STREAMSetValue(S, "AUTH:Types", Value); + else STREAMSetValue(S, Name, Value); ptr=GetNameValuePair(ptr, "\\S", "=", &Name, &Value); } diff --git a/SpawnPrograms.c b/SpawnPrograms.c index 10f30f6..b929e6b 100644 --- a/SpawnPrograms.c +++ b/SpawnPrograms.c @@ -354,9 +354,9 @@ STREAM *STREAMSpawnFunction(BASIC_FUNC Func, void *Data, const char *Config) if (S) { - //if we are doing to be sending raw data to the process, then flush always + //if we are doing to be sending raw data to the process, then flush always //otherwise we expect lines of text and flush on a line terminator - if (Flags & TTYFLAG_DATA) STREAMSetFlushType(S,FLUSH_ALWAYS,0,0); + if (Flags & TTYFLAG_DATA) STREAMSetFlushType(S,FLUSH_ALWAYS,0,0); else STREAMSetFlushType(S,FLUSH_LINE,0,0); Tempstr=FormatStr(Tempstr,"%d",pid); diff --git a/Stream.c b/Stream.c index 4f61cd0..470cbb4 100644 --- a/Stream.c +++ b/Stream.c @@ -1906,9 +1906,9 @@ int STREAMWriteBytes(STREAM *S, const char *Data, int DataLen) //thus the calling application always believes all data is written //Thus we only report errors if len==0; if (len > 0) result=STREAMInternalQueueBytes(S, i_data, len); - else if (S->OutEnd > S->StartPoint) + else if (S->OutEnd > S->StartPoint) { - result=STREAMInternalPushBytes(S, S->OutputBuff, S->OutEnd); + result=STREAMInternalPushBytes(S, S->OutputBuff, S->OutEnd); } Destroy(TempBuff); diff --git a/StreamAuth.c b/StreamAuth.c index e5fc93b..b014d3d 100644 --- a/StreamAuth.c +++ b/StreamAuth.c @@ -41,11 +41,9 @@ static int STREAMBasicAuthPasswordFile(const char *Path, STREAM *S) const char *ptr; int AuthResult=FALSE; - ptr=STREAMGetValue(S, "Auth:Basic"); - if (! StrValid(ptr)) return(FALSE); - - HTTPDecodeBasicAuth(ptr, &User, &Password); - AuthResult=PasswordFileCheck(Path, User, Password); + User=CopyStr(User, STREAMGetValue(S, "AUTH:User")); + Password=CopyStr(Password, STREAMGetValue(S, "AUTH:Password")); + AuthResult=PasswordFileCheck(Path, User, Password, NULL); Destroy(User); Destroy(Password); @@ -88,7 +86,7 @@ static int STREAMAuthProcess(STREAM *S, const char *AuthTypes) } else if (CompareStrNoCase(Key, "password-file")==0) AuthResult=STREAMBasicAuthPasswordFile(Value, S); - ptr=GetNameValuePair(ptr, ";", "=",&Key, &Value); + ptr=GetNameValuePair(ptr, ";", ":",&Key, &Value); } if (AuthResult==TRUE) STREAMSetValue(S, "STREAM:Authenticated", "Y"); @@ -107,7 +105,7 @@ int STREAMAuth(STREAM *S) { const char *ptr; - ptr=STREAMGetValue(S, "Authenticator"); + ptr=STREAMGetValue(S, "AUTH:Types"); if (! StrValid(ptr)) return(TRUE); return(STREAMAuthProcess(S, ptr)); diff --git a/Terminal.c b/Terminal.c index cc3c56a..ccafa8d 100644 --- a/Terminal.c +++ b/Terminal.c @@ -395,6 +395,12 @@ const char *TerminalAlignText(const char *Text, char **RetStr, int Flags, STREAM int pos=0, cols, rows, len, i; const char *ptr; + if (! Term) + { + *RetStr=CopyStr(*RetStr, Text); + return(Text+StrLen(Text)); + } + TerminalGeometry(Term, &cols, &rows); len=TerminalStrLen(Text); diff --git a/examples/uudecode.c b/examples/uudecode.c new file mode 100644 index 0000000..9d11596 --- /dev/null +++ b/examples/uudecode.c @@ -0,0 +1,18 @@ +#include "../libUseful.h" + +#define HELLO "JBSWY3DPEE======" + + +main(int argc, char *argv[]) +{ +char *Chars=NULL; +//char *Input="K:'1T<',Z+R]W=W6]U='5B92YC;VTO=V%T8V@_=CUH26XQ3F8S8F1D40``"; +char *Input="K:'1T<"; +int len; + +len=DecodeBytes(&Chars, Input, ENCODE_UUENC); +printf("%s\n", Chars); + +Chars=EncodeBytes(Chars, "Cat", 3, ENCODE_UUENC); +printf("%s\n", Chars); +}