Today's Page Hits: 244
I have more hair and it isn't so grey. :->
This page validates as XHTML 1.0, and will look much better in a browser that supports web standards, but it is accessible to any browser or Internet device. It was created using techniques detailed at glish.com/css/.
Given a directory path entry to a file, I want to find:
I can probably find a standard function to do this, but where is the fun in that?
You might notice I am being vague with the extension and basename, I'm giving the definition we know from common usage, not a precise one. We'll see why in a bit. And I am assuming we are passing in a file and not a directroy.
I've got the code sitting in the policy prototype, but I pulled it out to focus on and to do some fun unit testing. So, here is the code:
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
typedef struct {
char *ext;
char *path;
char *base;
char *file;
} policyAttributes_t;
int
main (int argc, char *argv[])
{
policyAttributes_t pat;
int rc = 0;
char *junk;
char *s;
/*
* Do some initialization.
*/
memset(&pat, '\0', sizeof(pat));
pat.path = strdup(argv[1]);
if (pat.path == NULL) {
...
}
/*
* Now we need the file.
*/
s = strrchr(argv[1], '/');
if (s) {
junk = strdup(s+1);
if (junk == NULL) {
...
}
pat.file = strdup(junk);
if (pat.file == NULL) {
...
}
s = strrchr(junk, '.');
if (s) {
pat.ext = strdup(s+1);
if (junk == NULL) {
...
}
*s = '\0';
}
pat.base = junk;
}
cleanup:
if (pat.path) {
printf("path = <%s>\n", pat.path);
free(pat.path);
}
if (pat.ext) {
printf("ext = <%s>\n", pat.ext);
free(pat.ext);
}
if (pat.base) {
printf("base = <%s>\n", pat.base);
free(pat.base);
}
if (pat.file) {
printf("file = <%s>\n", pat.file);
free(pat.file);
}
return (rc);
}
You can see I pulled it out of the other code - I preserved the pat variable. Anyway, I was mostly worried about the pointer manipulation, but I shouldn't have:
% ./a.out /foo/bar.c path = </foo/bar.c> ext = <c> base = <bar> file = <bar.c> % ./a.out /foo/grabba/yabba/bar.c path = </foo/grabba/yabba/bar.c> ext = <c> base = <bar> file = <bar.c> % ./a.out /foo/grabba/yabba/bar path = </foo/grabba/yabba/bar> base = <bar> file = <bar>
Now, in a traditional CIFS only world, everything would be hunky-dory. I could probably even do the 8+3 filename stuff. But we are wearing big boy pants now, so another test yields a result I do not agree with:
% ./a.out /foo/grabba/yabba/.cshrc path = </foo/grabba/yabba/.cshrc> ext = <cshrc> base = <> file = <.cshrc>
I would argue that the base name is '.cshrc' and there is no extension.
Anyone have any different views?
I knew I was close to having a lot more work last night. I spent a little bit of time this morning getting the error handling done the way I wanted for the evaluation (does a return of FALSE mean an error or not to match?). I also spliced the network parsing into the command line. Still needs to be reworked a bit, a network address is not a subnet after all. But, it now handles evaluating addresses correctly:
% /a.out -r tests/hulk.txt -d 12 -u 1167 -a 192.168.3.211 4, 25, 34000, uid == 1066 5, 30, 32000, uid == 1067 || uid == 1065 6, 15, 2000, uid == 1068 && gid == 500 7, 40, 8000, gid == 500 9, 40, 8000, day == 10 15, 3, 15000, subnet == 192.168.3.0/24 16, 3, 15000, subnet == 10.10.20.0/24 25, 2, 48000, ip == 192.168.2.211 1114, 30, 32000, !(uid == 1167 || uid == 1165) 1115, 40, 8000, !(day == 11) The matching policy is: 15, 3, 15000, subnet == 192.168.3.0/24 % ./a.out -r tests/hulk.txt -d 12 -u 1167 -a 192.168.2.211 ... The matching policy is: 25, 2, 48000, ip == 192.168.2.211 % ./a.out -r tests/hulk.txt -d 12 -u 1167 -a 10.10.20.5 ... The matching policy is: 16, 3, 15000, subnet == 10.10.20.0/24
Looks like I should have an option to dump the policies and by default not do it.
What I am struggling with now is how to differentiate between essentially testing this on the server and on any other machine. If it is the server, then I can state that the only command line parameters for attributes are those that I can pull out of a NFS request. I don't need anything else.
But if this is being run on a different computer, then I might need to provide some mock-up ability. E.g., I might want to set a netmask, a domain name, etc. In short, any of the secondary attributes.
I'm thinking of taking these off of the command line and putting them in a .speadm file. I want to focus on the command line looking like a NFS packet, but still allow for flexibility when debugging.
The latest code is at: speadm.c and speadm.h.
I'm not going to walk through the code right now. It is incomplete, mostly the command line parsing, and has XXXs all over the place. I pushed ahead just enough to get some simple integers working:
% cat tests/hulk.txt 4, 25, 34k, uid == 1066 6, 40, 8k, gid == 500 6, 40, 8k, day == 10 % ./a.out -r tests/hulk.txt -d 10 -u 1066 4, 25, 34000 uid == 1066 6, 40, 8000 gid == 500 6, 40, 8000 day == 10 The matching policy is: 4, 25, 34000 uid == 1066 % ./a.out -r tests/hulk.txt -d 10 4, 25, 34000 uid == 1066 6, 40, 8000 gid == 500 6, 40, 8000 day == 10 The matching policy is: 6, 40, 8000 day == 10
BTW: Notice what I meant about duplicate ids. I still need to fix that.
If you are trying the current code out, avoid the strings for right now. That would also include the networking tests.
What is in there now is the evaluation code, parsing of network and single machine addresses in the policies file, etc. I think I added 1k of code today and I can't figure out when. Well, 650 lines came in since the last blog entry.
The evaluation code stole the framework from the printing code. I'd love to abstract out the looping from the action to be performed. But, I think that may end up being more trouble than it is worth.
Hmm, I beefed up the tests just a bit and found that both '||' and '&&' are working:
% cat tests/hulk.txt 4, 25, 34k, uid == 1066 5, 30, 32k, uid == 1067 || uid == 1065 6, 15, 2k, uid == 1068 && gid == 500 7, 40, 8k, gid == 500 9, 40, 8k, day == 10 % ./a.out -r tests/hulk.txt -u 1067 4, 25, 34000 uid == 1066 5, 30, 32000 uid == 1067 || uid == 1065 6, 15, 2000 uid == 1068 && gid == 500 7, 40, 8000 gid == 500 9, 40, 8000 day == 10 The matching policy is: 5, 30, 32000 uid == 1067 || uid == 1065 % ./a.out -r tests/hulk.txt -u 1065 4, 25, 34000 uid == 1066 5, 30, 32000 uid == 1067 || uid == 1065 6, 15, 2000 uid == 1068 && gid == 500 7, 40, 8000 gid == 500 9, 40, 8000 day == 10 The matching policy is: 5, 30, 32000 uid == 1067 || uid == 1065 % ./a.out -r tests/hulk.txt -u 1068 -g 500 4, 25, 34000 uid == 1066 5, 30, 32000 uid == 1067 || uid == 1065 6, 15, 2000 uid == 1068 && gid == 500 7, 40, 8000 gid == 500 9, 40, 8000 day == 10 The matching policy is: 6, 15, 2000 uid == 1068 && gid == 500 % ./a.out -r tests/hulk.txt -u 1068 -g 501 4, 25, 34000 uid == 1066 5, 30, 32000 uid == 1067 || uid == 1065 6, 15, 2000 uid == 1068 && gid == 500 7, 40, 8000 gid == 500 9, 40, 8000 day == 10 No matching policy, default would apply.
What about '!'?
% ./a.out -r tests/hulk.txt -d 12 -u 1167 4, 25, 34000, uid == 1066 5, 30, 32000, uid == 1067 || uid == 1065 6, 15, 2000, uid == 1068 && gid == 500 7, 40, 8000, gid == 500 9, 40, 8000, day == 10 10, 30, 32000, !(uid == 1167 || uid == 1165) 15, 40, 8000, !(day == 11) The matching policy is: 10, 30, 32000, !(uid == 1167 || uid == 1165)
Looks wrong (notice I fixed a missing ',' before the policy attribute-expression). Hmm, here is the bug:
bLHS = spe_eval_thunk(si->si_branches[0], pat, &sa);
/*
* Lazy, but only 1 op - which is '!'.
*/
if (b == TRUE) {
b = FALSE;
} else {
b = TRUE;
}
That should have been a test on bLHS. Again, quick coding leads to bugs. With the fix:
% ./a.out -r tests/hulk.txt -d 12 -u 1167 4, 25, 34000, uid == 1066 5, 30, 32000, uid == 1067 || uid == 1065 6, 15, 2000, uid == 1068 && gid == 500 7, 40, 8000, gid == 500 9, 40, 8000, day == 10 10, 30, 32000, !(uid == 1167 || uid == 1165) 15, 40, 8000, !(day == 11) The matching policy is: 15, 40, 8000, !(day == 11)
The latest code is at: speadm.c and speadm.h.