aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/sledjchisl/sledjchisl.c
diff options
context:
space:
mode:
authoronefang2021-07-30 14:00:10 +1000
committeronefang2021-07-30 14:00:10 +1000
commitf6e5f4a2ea01452e49062ac807c9c763fbe7b2a0 (patch)
treef1107579ff0b4d91ffb60b45c39bb11353079033 /src/sledjchisl/sledjchisl.c
parentPut the grids own bin directory in the path. (diff)
downloadopensim-SC-f6e5f4a2ea01452e49062ac807c9c763fbe7b2a0.zip
opensim-SC-f6e5f4a2ea01452e49062ac807c9c763fbe7b2a0.tar.gz
opensim-SC-f6e5f4a2ea01452e49062ac807c9c763fbe7b2a0.tar.bz2
opensim-SC-f6e5f4a2ea01452e49062ac807c9c763fbe7b2a0.tar.xz
Shift Lua functions up near the top.
Diffstat (limited to '')
-rw-r--r--src/sledjchisl/sledjchisl.c551
1 files changed, 288 insertions, 263 deletions
diff --git a/src/sledjchisl/sledjchisl.c b/src/sledjchisl/sledjchisl.c
index 16876f0..b88b1a5 100644
--- a/src/sledjchisl/sledjchisl.c
+++ b/src/sledjchisl/sledjchisl.c
@@ -581,6 +581,28 @@ static char *getStrH(qhashtbl_t *hash, char *key)
581} 581}
582 582
583 583
584static void bitch(reqData *Rd, char *message, char *log)
585{
586 addStrL(Rd->errors, message);
587 E("%s %s %s - %s %s", getStrH(Rd->headers, "REMOTE_ADDR"), Rd->shs.UUID, Rd->shs.name, message, log);
588}
589
590/* "A token cookie that references a non-existent session, its value should be replaced immediately to prevent session fixation."
591https://owasp.org/www-community/attacks/Session_fixation
592 Which describes the problem, but offers no solution.
593 See https://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication?rq=1.
594I think this means send a new cookie.
595 I clear out the cookies and send blank ones with -1 maxAge, so they should get deleted.
596*/
597static void bitchSession(reqData *Rd, char *message, char *log)
598{
599 if ('\0' != message[0])
600 addStrL(Rd->errors, message);
601 C("%s %s %s - %s %s", getStrH(Rd->headers, "REMOTE_ADDR"), Rd->shs.UUID, Rd->shs.name, message, log);
602 Rd->shs.status = SHS_BOGUS;
603}
604
605
584char *myHMAC(char *in, boolean b64) 606char *myHMAC(char *in, boolean b64)
585{ 607{
586 EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); // Gets renamed to EVP_MD_CTX_new() in later versions. 608 EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); // Gets renamed to EVP_MD_CTX_new() in later versions.
@@ -629,6 +651,272 @@ void PrintTable(lua_State *L)
629 } 651 }
630} 652}
631 653
654typedef struct _qLua qLua;
655struct _qLua
656{
657 int type;
658 union
659 {
660 boolean b;
661 int i;
662 float f;
663 char *s;
664 qtreetbl_t *t;
665 } v;
666};
667
668qLua *qLuaGet(qtreetbl_t *tree, char *key)
669{
670 return (qLua *) tree->get(tree, key, NULL, false);
671}
672
673qtreetbl_t *lua2tree()
674{
675 qtreetbl_t *ret = qtreetbl(0);
676
677 if (NULL != ret)
678 {
679 qLua q;
680
681 lua_pushnil(L); // +1 nil, first key
682 while(lua_next(L, -2) != 0) // -1 key, +2 next key, value (or 0 if nothing left in table)
683 {
684 // stack now contains: -1 => value; -2 => key; -3 => table
685 // copy the key so that lua_tostring does not modify the original
686 lua_pushvalue(L, -2);
687 // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
688 char *n = (char *) lua_tostring(L, -1); // 0, modifies key copy
689 q.type = lua_type(L, -2); // 0
690 // Numbers can convert to strings, so check for numbers before checking for strings.
691 // On the other hand, strings that can be converted to numbers also pass lua_isnumber(). sigh
692 switch(q.type)
693 {
694 case LUA_TBOOLEAN : {q.v.b = lua_toboolean(L, -2); break;}
695 case LUA_TINTEGER : {q.v.i = lua_tointeger(L, -2); break;}
696 case LUA_TNUMBER : {q.v.f = lua_tonumber(L, -2); break;}
697 case LUA_TSTRING : {q.v.s = (char *) lua_tostring(L, -2); break;}
698 case LUA_TTABLE : {lua_pushvalue(L, -2); q.v.t = lua2tree(); lua_pop(L, 1); break;}
699
700 default :
701 {
702 q.v.s = (char *) lua_tostring(L, -2); // 0
703 E("Unknown Lua variable type for %s = %s is %d", n, q.v.s, q.type);
704 break;
705 }
706 }
707 ret->put(ret, n, &q, sizeof(qLua));
708 // pop value + copy of key, leaving original key
709 lua_pop(L, 2); // -2 value and copy of key
710 // stack now contains: -1 => key; -2 => table
711 }
712 }
713 else
714 {
715 D("No memory left.");
716 perror_msg("Unable to allocate memory");
717 }
718
719 return ret;
720}
721
722qtreetbl_t *Lua2tree(char *file, char *var)
723{
724 qtreetbl_t *ret = NULL;
725 struct stat st;
726
727 if (0 != lstat(file, &st))
728 {
729 D("No %s file.", file);
730 perror_msg("Unable to stat %s", file);
731 }
732 else
733 {
734 if (luaL_loadfile(L, file)) // +1 the chunk or an error message. If something went wrong, error message is at the top of the stack.
735 E("Couldn't load Lua file: %s", lua_tostring(L, -1)); // 0
736 else
737 {
738 if (lua_pcall(L, 0, LUA_MULTRET, 0)) // +1 result or an error message. Except we get 0 or error?
739 {
740 E("Failed to run Lua script: %s", lua_tostring(L, -1)); // 0
741 lua_pop(L, 1); // -1 chunk or error message
742 }
743 else
744 {
745 lua_getglobal(L, var); // +1 the value of var
746 ret = lua2tree();
747 lua_pop(L, 1); // -1 var
748 }
749 }
750 lua_pop(L, 1); // -1 chunk or error message
751 }
752 return ret;
753}
754
755
756int Lua2hashtbl(char *file, qhashtbl_t *hash, char *var)
757{
758 int ret = FALSE;
759 struct stat st;
760
761 if (0 != lstat(file, &st))
762 {
763 D("No %s file.", file);
764 perror_msg("Unable to stat %s", file);
765 return FALSE;
766 }
767 else
768 {
769 int status = luaL_loadfile(L, file); // +1 the chunk or an error message.
770 if (status) // If something went wrong, error message is at the top of the stack.
771 E("Couldn't load Lua file: %s", lua_tostring(L, -1)); // 0
772 else
773 {
774 int result = lua_pcall(L, 0, LUA_MULTRET, 0); // +1 result or an error message. Except we get 0 or error?
775 if (result)
776 {
777 E("Failed to run Lua script: %s", lua_tostring(L, -1)); // 0
778 lua_pop(L, 1); // -1 chunk or error message
779 }
780 else
781 {
782 lua_getglobal(L, var); // +1 the value of var
783 lua_pushnil(L); // +1 nil, first key
784 while(lua_next(L, -2) != 0) // -1 key, +2 next key, value (or 0 if nothing left in table)
785 {
786 char *n = (char *) lua_tostring(L, -2); // 0
787
788 // Numbers can convert to strings, so check for numbers before checking for strings.
789 // On the other hand, strings that can be converted to numbers also pass lua_isnumber(). sigh
790 if (lua_isnumber(L, -1)) // 0
791 {
792 float v = lua_tonumber(L, -1); // 0
793 hash->put(hash, n, &v, sizeof(float));
794 }
795 else if (lua_isstring(L, -1)) // 0
796 hash->putstr(hash, n, (char *) lua_tostring(L, -1)); // 0
797 else if (lua_isboolean(L, -1)) // 0
798 {
799 int v = lua_toboolean(L, -1); // 0
800 hash->putint(hash, n, v);
801 }
802 else
803 {
804 char *v = (char *) lua_tostring(L, -1); // 0
805 E("Unknown Lua variable type for %s = %s", n, v);
806 }
807 lua_pop(L, 1); // -1 value
808 }
809 lua_pop(L, 1); // -1 var
810 ret = TRUE;
811 }
812 }
813 }
814 lua_pop(L, 1); // -1 chunk or error message
815 return ret;
816}
817
818int LuaToHash(reqData *Rd, char *file, char *var, qhashtbl_t *tnm, int ret, struct stat *st, struct timespec *now, char *type)
819{
820 struct timespec then;
821
822 if (-1 == clock_gettime(CLOCK_REALTIME, &then))
823 perror_msg("Unable to get the time.");
824 I("Reading %s file %s", type, file);
825 if (!Lua2hashtbl(file, tnm, var))
826 {
827 bitch(Rd, "Broken thing.", "Can't run file.");
828 ret++;
829 }
830 else
831 {
832 if (-1 == clock_gettime(CLOCK_REALTIME, now))
833 perror_msg("Unable to get the time.");
834 double n = (now->tv_sec * 1000000000.0) + now->tv_nsec;
835 double t = (then.tv_sec * 1000000000.0) + then.tv_nsec;
836 T("Reading %s file took %lf seconds", type, (n - t) / 1000000000.0);
837 }
838
839 return ret;
840}
841
842
843boolean writeLuaDouble(reqData *Rd, int fd, char *file, char *name, double number)
844{
845 boolean ret = TRUE;
846// TODO - putting these in Lua as numbers causes lua_tolstring to barf when we read them. Though Lua is supposed to convert between numbers and strings.
847 char *t = xmprintf(" ['%s'] = '%f',\n", name, number); // NOTE - default precision is 6 decimal places.
848 size_t l = strlen(t);
849
850 if (l != writeall(fd, t, l))
851 {
852 perror_msg("Writing %s", file);
853 ret = FALSE;
854 }
855 free(t);
856 return ret;
857}
858
859boolean writeLuaInteger(reqData *Rd, int fd, char *file, char *name, long number)
860{
861 boolean ret = TRUE;
862// TODO - putting these in Lua as numbers causes lua_tolstring to barf when we read them. Though Lua is supposed to convert between numbers and strings.
863 char *t = xmprintf(" ['%s'] = '%ld',\n", name, number);
864 size_t l = strlen(t);
865
866 if (l != writeall(fd, t, l))
867 {
868 perror_msg("Writing %s", file);
869 ret = FALSE;
870 }
871 free(t);
872 return ret;
873}
874
875boolean writeLuaString(reqData *Rd, int fd, char *file, char *name, char *string)
876{
877 boolean ret = TRUE;
878
879 if (NULL == string)
880 string = getStrH(Rd->stuff, name);
881
882 size_t l = strlen(string);
883 char *t0 = xmalloc(l * 2 + 1);
884 int i, j = 0;
885
886// TODO - maybe escape other non printables as well?
887 for (i = 0; i < l; i++)
888 {
889 // We don't need to escape [] here, coz we are using '' below. Same applies to ", but do it anyway.
890 switch(string[i])
891 {
892 case '\n':
893 case '\\':
894 case '\'':
895 case '"':
896 t0[j++] = '\\'; break;
897 }
898 if ('\n' == string[i])
899 t0[j++] = 'n';
900 else if ('\r' == string[i])
901 ;
902 else
903 t0[j++] = string[i];
904 }
905 t0[j] = '\0';
906
907 char *t1 = xmprintf(" ['%s'] = '%s',\n", name, t0);
908
909 l = strlen(t1);
910 if (l != writeall(fd, t1, l))
911 {
912 perror_msg("Writing %s to %s", name, file);
913 ret = FALSE;
914 }
915 free(t1);
916 free(t0);
917 return ret;
918}
919
632 920
633void doTmuxCmd(char *format, ...) 921void doTmuxCmd(char *format, ...)
634{ 922{
@@ -3478,28 +3766,6 @@ https://stackoverflow.com/questions/16891729/best-practices-salting-peppering-pa
3478qlisttbl_t *accountLevels = NULL; 3766qlisttbl_t *accountLevels = NULL;
3479 3767
3480 3768
3481static void bitch(reqData *Rd, char *message, char *log)
3482{
3483 addStrL(Rd->errors, message);
3484 E("%s %s %s - %s %s", getStrH(Rd->headers, "REMOTE_ADDR"), Rd->shs.UUID, Rd->shs.name, message, log);
3485}
3486
3487/* "A token cookie that references a non-existent session, its value should be replaced immediately to prevent session fixation."
3488https://owasp.org/www-community/attacks/Session_fixation
3489 Which describes the problem, but offers no solution.
3490 See https://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication?rq=1.
3491I think this means send a new cookie.
3492 I clear out the cookies and send blank ones with -1 maxAge, so they should get deleted.
3493*/
3494static void bitchSession(reqData *Rd, char *message, char *log)
3495{
3496 if ('\0' != message[0])
3497 addStrL(Rd->errors, message);
3498 C("%s %s %s - %s %s", getStrH(Rd->headers, "REMOTE_ADDR"), Rd->shs.UUID, Rd->shs.name, message, log);
3499 Rd->shs.status = SHS_BOGUS;
3500}
3501
3502
3503// The ancient, insecure since 2011, Second Life / OpenSim password hashing algorithm. 3769// The ancient, insecure since 2011, Second Life / OpenSim password hashing algorithm.
3504char *newSLOSsalt(reqData *Rd) 3770char *newSLOSsalt(reqData *Rd)
3505{ 3771{
@@ -3564,169 +3830,6 @@ t("checkSLOSpassword(%s, %s, %s, ", password, salt, passwordHash, fail);
3564} 3830}
3565 3831
3566 3832
3567typedef struct _qLua qLua;
3568struct _qLua
3569{
3570 int type;
3571 union
3572 {
3573 boolean b;
3574 int i;
3575 float f;
3576 char *s;
3577 qtreetbl_t *t;
3578 } v;
3579};
3580
3581qLua *qLuaGet(qtreetbl_t *tree, char *key)
3582{
3583 return (qLua *) tree->get(tree, key, NULL, false);
3584}
3585
3586qtreetbl_t *lua2tree()
3587{
3588 qtreetbl_t *ret = qtreetbl(0);
3589
3590 if (NULL != ret)
3591 {
3592 qLua q;
3593
3594 lua_pushnil(L); // +1 nil, first key
3595 while(lua_next(L, -2) != 0) // -1 key, +2 next key, value (or 0 if nothing left in table)
3596 {
3597 char *n = (char *) lua_tostring(L, -2); // 0
3598
3599 q.type = lua_type(L, -1); // 0
3600 // Numbers can convert to strings, so check for numbers before checking for strings.
3601 // On the other hand, strings that can be converted to numbers also pass lua_isnumber(). sigh
3602 switch(q.type)
3603 {
3604 case LUA_TBOOLEAN : {q.v.b = lua_toboolean(L, -1); break;}
3605 case LUA_TINTEGER : {q.v.i = lua_tointeger(L, -1); break;}
3606 case LUA_TNUMBER : {q.v.f = lua_tonumber(L, -1); break;}
3607 case LUA_TSTRING : {q.v.s = (char *) lua_tostring(L, -1); break;}
3608 case LUA_TTABLE : {q.v.t = lua2tree(); break;}
3609
3610 default :
3611 {
3612 q.v.s = (char *) lua_tostring(L, -1); // 0
3613 E("Unknown Lua variable type for %s = %s is %d", n, q.v.s, q.type);
3614 break;
3615 }
3616 }
3617 ret->put(ret, n, &q, sizeof(qLua));
3618 lua_pop(L, 1); // -1 value
3619 }
3620 }
3621 else
3622 {
3623 D("No memory left.");
3624 perror_msg("Unable to allocate memory");
3625 }
3626
3627 return ret;
3628}
3629
3630qtreetbl_t *Lua2tree(char *file, char *var)
3631{
3632 qtreetbl_t *ret = NULL;
3633 struct stat st;
3634
3635 if (0 != lstat(file, &st))
3636 {
3637 D("No %s file.", file);
3638 perror_msg("Unable to stat %s", file);
3639 }
3640 else
3641 {
3642 if (luaL_loadfile(L, file)) // +1 the chunk or an error message. If something went wrong, error message is at the top of the stack.
3643 E("Couldn't load Lua file: %s", lua_tostring(L, -1)); // 0
3644 else
3645 {
3646 if (lua_pcall(L, 0, LUA_MULTRET, 0)) // +1 result or an error message. Except we get 0 or error?
3647 {
3648 E("Failed to run Lua script: %s", lua_tostring(L, -1)); // 0
3649 lua_pop(L, 1); // -1 chunk or error message
3650 }
3651 else
3652 {
3653 lua_getglobal(L, var); // +1 the value of var
3654 ret = lua2tree();
3655 lua_pop(L, 1); // -1 var
3656 }
3657 }
3658 lua_pop(L, 1); // -1 chunk or error message
3659 }
3660 return ret;
3661}
3662
3663
3664int LuaToHash(reqData *Rd, char *file, char *var, qhashtbl_t *tnm, int ret, struct stat *st, struct timespec *now, char *type)
3665{
3666 struct timespec then;
3667
3668 if (-1 == clock_gettime(CLOCK_REALTIME, &then))
3669 perror_msg("Unable to get the time.");
3670 I("Reading %s file %s", type, file);
3671 if (0 != stat(file, st))
3672 {
3673 D("No %s file.", file);
3674 perror_msg("Unable to stat %s", file);
3675 ret++;
3676 }
3677 else
3678 {
3679 int status = luaL_loadfile(Rd->L, file), result;
3680
3681 if (status)
3682 {
3683 bitch(Rd, "No such thing.", "Can't load file.");
3684 E("Couldn't load file: %s", lua_tostring(Rd->L, -1));
3685 ret++;
3686 }
3687 else
3688 {
3689 result = lua_pcall(Rd->L, 0, LUA_MULTRET, 0);
3690
3691 if (result)
3692 {
3693 bitch(Rd, "Broken thing.", "Can't run file.");
3694 E("Failed to run script: %s", lua_tostring(Rd->L, -1));
3695 ret++;
3696 }
3697 else
3698 {
3699 lua_getglobal(Rd->L, var);
3700 lua_pushnil(Rd->L);
3701
3702 while(lua_next(Rd->L, -2) != 0)
3703 {
3704 char *n = (char *) lua_tostring(Rd->L, -2);
3705
3706 if (lua_isstring(Rd->L, -1))
3707 {
3708 tnm->putstr(tnm, n, (char *) lua_tostring(Rd->L, -1));
3709d("Lua reading (%s) %s = %s", type, n, getStrH(tnm, n));
3710 }
3711 else
3712 {
3713 char *v = (char *) lua_tostring(Rd->L, -1);
3714 W("Unknown Lua variable type for %s = %s", n, v);
3715 }
3716 lua_pop(Rd->L, 1);
3717 }
3718
3719 if (-1 == clock_gettime(CLOCK_REALTIME, now))
3720 perror_msg("Unable to get the time.");
3721 double n = (now->tv_sec * 1000000000.0) + now->tv_nsec;
3722 double t = (then.tv_sec * 1000000000.0) + then.tv_nsec;
3723 T("Reading %s file took %lf seconds", type, (n - t) / 1000000000.0);
3724 }
3725 }
3726 }
3727
3728 return ret;
3729}
3730 3833
3731 3834
3732char *checkLinky(reqData *Rd) 3835char *checkLinky(reqData *Rd)
@@ -4113,84 +4216,6 @@ systemFolders sysFolders[] =
4113 {"Trash", 14}, 4216 {"Trash", 14},
4114 {NULL, -1} 4217 {NULL, -1}
4115}; 4218};
4116
4117boolean writeLuaDouble(reqData *Rd, int fd, char *file, char *name, double number)
4118{
4119 boolean ret = TRUE;
4120// TODO - putting these in Lua as numbers causes lua_tolstring to barf when we read them. Though Lua is supposed to convert between numbers and strings.
4121 char *t = xmprintf(" ['%s'] = '%f',\n", name, number); // NOTE - default precision is 6 decimal places.
4122 size_t l = strlen(t);
4123
4124 if (l != writeall(fd, t, l))
4125 {
4126 perror_msg("Writing %s", file);
4127 ret = FALSE;
4128 }
4129 free(t);
4130 return ret;
4131}
4132
4133boolean writeLuaInteger(reqData *Rd, int fd, char *file, char *name, long number)
4134{
4135 boolean ret = TRUE;
4136// TODO - putting these in Lua as numbers causes lua_tolstring to barf when we read them. Though Lua is supposed to convert between numbers and strings.
4137 char *t = xmprintf(" ['%s'] = '%ld',\n", name, number);
4138 size_t l = strlen(t);
4139
4140 if (l != writeall(fd, t, l))
4141 {
4142 perror_msg("Writing %s", file);
4143 ret = FALSE;
4144 }
4145 free(t);
4146 return ret;
4147}
4148
4149boolean writeLuaString(reqData *Rd, int fd, char *file, char *name, char *string)
4150{
4151 boolean ret = TRUE;
4152
4153 if (NULL == string)
4154 string = getStrH(Rd->stuff, name);
4155
4156 size_t l = strlen(string);
4157 char *t0 = xmalloc(l * 2 + 1);
4158 int i, j = 0;
4159
4160// TODO - maybe escape other non printables as well?
4161 for (i = 0; i < l; i++)
4162 {
4163 // We don't need to escape [] here, coz we are using '' below. Same applies to ", but do it anyway.
4164 switch(string[i])
4165 {
4166 case '\n':
4167 case '\\':
4168 case '\'':
4169 case '"':
4170 t0[j++] = '\\'; break;
4171 }
4172 if ('\n' == string[i])
4173 t0[j++] = 'n';
4174 else if ('\r' == string[i])
4175 ;
4176 else
4177 t0[j++] = string[i];
4178 }
4179 t0[j] = '\0';
4180
4181 char *t1 = xmprintf(" ['%s'] = '%s',\n", name, t0);
4182
4183 l = strlen(t1);
4184 if (l != writeall(fd, t1, l))
4185 {
4186 perror_msg("Writing %s to %s", name, file);
4187 ret = FALSE;
4188 }
4189 free(t1);
4190 free(t0);
4191 return ret;
4192}
4193
4194static void accountWrite(reqData *Rd) 4219static void accountWrite(reqData *Rd)
4195{ 4220{
4196 char *uuid = getStrH(Rd->database, "UserAccounts.PrincipalID"); 4221 char *uuid = getStrH(Rd->database, "UserAccounts.PrincipalID");