From b2cc25f50c05545261b3f98115149f9707e3ab5b Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Fri, 25 Oct 2013 00:58:23 +0100 Subject: [PATCH] add code to generate uuid version 3 and 5. With this we can generate the same uuid for a given name all the time --- configure.ac | 1 + include/session.h | 2 +- include/user.h | 15 ++++--- include/uuid.h | 31 ++++++++++---- src/Makefile.am | 7 ++-- src/router/route.c | 93 ++++++++++++++++++++++++++++++++++++++++++ src/testers/uuid.c | 44 ++++++++++++++++---- src/user/save.c | 2 +- src/uuid/Makefile.am | 12 ++++++ src/uuid/_format3or5.c | 55 +++++++++++++++++++++++++ src/uuid/compare.c | 35 ++++++++++++++++ src/uuid/parse.c | 38 +++++++++++++++++ src/uuid/unparse.c | 35 ++++++++++++++++ src/uuid/uuid.c | 56 +++++++++++++++++++++++++ src/uuid/version1.c | 38 +++++++++++++++++ src/uuid/version3.c | 69 +++++++++++++++++++++++++++++++ src/uuid/version5.c | 69 +++++++++++++++++++++++++++++++ 17 files changed, 575 insertions(+), 27 deletions(-) create mode 100644 src/uuid/Makefile.am create mode 100644 src/uuid/_format3or5.c create mode 100644 src/uuid/compare.c create mode 100644 src/uuid/parse.c create mode 100644 src/uuid/unparse.c create mode 100644 src/uuid/uuid.c create mode 100644 src/uuid/version1.c create mode 100644 src/uuid/version3.c create mode 100644 src/uuid/version5.c diff --git a/configure.ac b/configure.ac index 0cee415..d25dd42 100644 --- a/configure.ac +++ b/configure.ac @@ -98,6 +98,7 @@ AC_CONFIG_FILES([Makefile src/user/Makefile src/config/Makefile src/router/Makefile + src/uuid/Makefile docs/Makefile config/Makefile tests/Makefile]) diff --git a/include/session.h b/include/session.h index a411c5c..ccc68fa 100644 --- a/include/session.h +++ b/include/session.h @@ -36,8 +36,8 @@ CLASS(Session) { char id[37]; unsigned long hash; - time_t livetime; + time_t livetime; User user; }; diff --git a/include/user.h b/include/user.h index 147677e..e12575c 100644 --- a/include/user.h +++ b/include/user.h @@ -30,13 +30,16 @@ CLASS(User) { - char * email; - char * firstname; - char * surname; + char id[37]; + unsigned long hash; - size_t * nemail; - size_t * nfirstname; - size_t * nsurname; + char * email; + char * firstname; + char * surname; + + size_t * nemail; + size_t * nfirstname; + size_t * nsurname; }; User userLoad(User, Storage); diff --git a/include/uuid.h b/include/uuid.h index b3bde29..641316f 100644 --- a/include/uuid.h +++ b/include/uuid.h @@ -29,6 +29,7 @@ #ifndef __UUID_H__ #define __UUID_H__ +#include #include #include @@ -36,21 +37,35 @@ #include "commons.h" +typedef char UuidString[37]; + CLASS(Uuid) { union { uuid_t value; struct { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_low_version; - uint8_t clk_seq_hi_res; - uint8_t clk_seq_low; - uint16_t node_hi; - uint32_t node_low; + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_version; + uint8_t clk_seq_hi_res; + uint8_t clk_seq_low; + unsigned char node[6]; } elements; } uuid; }; -#endif // __ASSET_H__ +/* + * generator functions...these are not really part of the object + * but generate a uuid object. + */ +Uuid uuidVersion1(); +Uuid uuidVersion3(const unsigned char *, size_t, Uuid); +Uuid uuidVersion5(const unsigned char *, size_t, Uuid); + +void uuidUnparse(Uuid, UuidString); +Uuid uuidParse(const UuidString); + +int uuidCompare(Uuid, Uuid); + +#endif // __UUID_H__ // vim: set ts=4 sw=4: diff --git a/src/Makefile.am b/src/Makefile.am index 1159b5e..b3eaf63 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,8 @@ TRBASELIBS = class/libclass.la \ queue/libqueue.la \ logger/liblogger.la \ tree/libtree.la \ - stream/libstream.la + stream/libstream.la \ + uuid/libuuid.la TRHTTPSERVER = http/libhttp.la \ asset/libasset.la \ @@ -34,7 +35,7 @@ TR = ./application/.libs/libapplication.a \ ./router/.libs/librouter.a TRLIBS = -ltrutils -ltrhttpserver -ltrbase -USEDLIBS = -lrt -lssl -lldap -lgdbm -luuid -ldl +USEDLIBS = -lrt -lssl -lcrypto -lldap -lgdbm -luuid -ldl AM_CFLAGS += -I../include/ @@ -61,4 +62,4 @@ taskrambler_LDFLAGS = -Wl,--export-dynamic \ SUBDIRS = asset auth cbuf class hash queue http \ logger server session socket stream tree application \ - storage user config router + storage user config router uuid diff --git a/src/router/route.c b/src/router/route.c index 5a6e2c0..cb3f2c8 100644 --- a/src/router/route.c +++ b/src/router/route.c @@ -135,6 +135,99 @@ routerRoute( /** * \todo somewhere here or above access control have to take place + * Default policy should be deny, anyway, there are a few resource + * that should be accessible even when not logged in...the are at + * least most of the assets as well as functions like version or + * sessinfo and in fact currentuse to have a way to find out that + * one is not logged in. + * In general a deny will be handled by storing an error message in + * some stash and then trigger a redirect to the login page. + * To be really rbac it seems neccessary to me to create a user + * "not logged in" and assign him the exceptions to the default + * deny policy. + * For the moment I assume that if there is no resource for the + * URL in the application it must be an asset and just return NULL + * indication that we still have no response for the request. + * Another thought... resources will be created dynamically by + * creating tasks or users or anything. + * Each of these resources may have options to admin them. This means + * most of the time to be able to modify them but additionally the + * creater of the resource might need the right to modify the + * rbac rules that apply to that resource. + * So, if I keep the real resources and their rbac configuration + * separated as planned it might be neccessary to give the creater + * of a resource the ability to modify both. + * + * So lets assume user georg creates a task that might be identified + * by /task/uuid(task). Then additionally an rbac resource will be + * created identified by /rbac_resource/uuid(/task/uuid(task)). + * User georg will have all rights on both resources. + * This means that rbac resources are resources by their own but how + * to control the access to these, I can't build another rbac resource + * and another and and and... so I think it is neccessary that every + * resource as it is has to hold their access in itself. + * The creating user will gain access to all REST operations as well + * as the right to change access control (which again are REST operations + * on these. + * + * Sidenote: I use a slightly differen naming than the ansi spec uses + * I the term resource for object and action for operation. + * + * So most resources end up with the following set of possible actions: + * - create: (well obviously this is only useful for list resources + * eg. the tasklist of a new project) + * - read: be able to display the resource... + * (again there is a special thing with lists here. This + * only gives the right to see the list at all. When + * generating the list the access rights on each entry + * has to be checked and if there is no read right for it + * it should not be included in the list.) + * - update: be able to update a resource. + * (this makes no sense for list resources as the change when + * their members change) + * - delete: be able to remove a resource. + * (on list resources this should only be allowed if the list + * is empty, this is the only consistent behaviour I can think + * of because you can't always assume that by removing a + * list ii's associated members should also be removed) + * - rbac_read: + * - rbac_update: + * + * Well, rbac assignes only roles to resources... in that case, how can I + * achieve per user rights for specific resources... one way would be + * to give every user its own role, which makes the whole concept kind + * of useless. + * + * Then I could allow everyone to create new roles on demand. Then + * a user would create a role that allows others to view the resource + * and then add user to this role. This role creation could be done + * automatically and in the UI the user simply only adds the users + * that should have access to the specific action. + * On the other hand the user might associate an action on the resource + * to an existing role. + * thus giving, for example, all team members the right to use the + * according action. Again in the UI this would be a simple select + * from a list. + * Still it seems neccessary to have a suer_private role where only + * this one user is in and that has full access to all resource actions + * of each resource the user is creating...and if there is such a thing + * no new roles will be created when allowing others to take actions + * on specific resources...simply add the action to the private role of + * the other user. + * This private roles can be almost automatic. + * (created when user is created, removed when he is removed, etc. etc) + * Regarding the session...I hink it ok to use our sessions to store + * The resulting access rights defined by the roles the user is in. + * On the other hand...if we store them stere no immediate feedback is + * possible when one of the roles have been changed....well, maybe + * there is...each existing session for users that are associated with + * the changed role have to be updated. That is in any case better + * than calculating all the access right on every reqeust. + * So, what we have in place right now are users and sessions. Both + * can be extended to the needs for rbac. + * What we still need is a definition of resources and actions that + * build up a permission and roles in it self that will associate user + * with permissions. */ if (NULL == function) { diff --git a/src/testers/uuid.c b/src/testers/uuid.c index 8ab3022..0c9c235 100644 --- a/src/testers/uuid.c +++ b/src/testers/uuid.c @@ -1,18 +1,46 @@ -#include #include +#include + +#include "class.h" +#include "uuid.h" + +#include "commons.h" +#include "utils/memory.h" + + +#define UUID_NS "4f947b70-6f9f-43b6-8dc1-1321977c8240" + int main(int argc, char * argv[]) { - uuid_t uuid; - char uuid_str[37]; + UuidString uuid_str; + + Uuid nsid = uuidParse(UUID_NS); + Uuid ver1 = uuidVersion1(); + Uuid ver3 = uuidVersion3("foo", 3, nsid); + Uuid ver5 = uuidVersion3("foo", 5, nsid); + + uuidUnparse(nsid, uuid_str); + printf("nsid: %s\n", uuid_str); + + uuidUnparse(ver1, uuid_str); + printf("nsid: %s\n", uuid_str); + + uuidUnparse(ver3, uuid_str); + printf("nsid: %s\n", uuid_str); + + uuidUnparse(ver5, uuid_str); + printf("nsid: %s\n", uuid_str); - uuid_generate(uuid); - uuid_unparse(uuid, uuid_str); + delete(ver5); + delete(ver3); + delete(ver1); + delete(nsid); - printf("%s\n", uuid_str); + memCleanup(); - return 0; + return 0; } -// vim: set ts=4 sw=4: +// vim: set et ts=4 sw=4: diff --git a/src/user/save.c b/src/user/save.c index e8a3ce0..f4280d2 100644 --- a/src/user/save.c +++ b/src/user/save.c @@ -44,7 +44,7 @@ userSave(User this, Storage storage) */ storageUpdate( storage, - this->email, *this->nemail, + this->id, 36, this->email, storage_size); } diff --git a/src/uuid/Makefile.am b/src/uuid/Makefile.am new file mode 100644 index 0000000..fe48a52 --- /dev/null +++ b/src/uuid/Makefile.am @@ -0,0 +1,12 @@ +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = subdir-objects + +UUID = uuid.c version1.c version3.c version5.c _format3or5.c \ + parse.c unparse.c compare.c + +AM_CFLAGS += -I../../include/ + +noinst_LTLIBRARIES = libuuid.la + +libuuid_la_SOURCES = $(UUID) +libuuid_la_CFLAGS = $(AM_CFLAGS) diff --git a/src/uuid/_format3or5.c b/src/uuid/_format3or5.c new file mode 100644 index 0000000..f4efec3 --- /dev/null +++ b/src/uuid/_format3or5.c @@ -0,0 +1,55 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2013 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// for memcpy +#include + +// for ntohl and similar +#include + +// for already available uuid functionality +#include + +#include "class.h" +#include "uuid.h" + +void +_uuidFormat3or5(Uuid uuid, unsigned char hash[16], int version) +{ + /* convert UUID to local byte order */ + memcpy((uuid->uuid).value, hash, 16); + + (uuid->uuid).elements.time_low = + ntohl((uuid->uuid).elements.time_low); + (uuid->uuid).elements.time_mid = + ntohs((uuid->uuid).elements.time_mid); + (uuid->uuid).elements.time_hi_version = + ntohs((uuid->uuid).elements.time_hi_version); + + /* put in the variant and version bits */ + (uuid->uuid).elements.time_hi_version &= 0x0FFF; + (uuid->uuid).elements.time_hi_version |= (version << 12); + (uuid->uuid).elements.clk_seq_hi_res &= 0x3F; + (uuid->uuid).elements.clk_seq_hi_res |= 0x80; +} + +// vim: set ts=4 sw=4: diff --git a/src/uuid/compare.c b/src/uuid/compare.c new file mode 100644 index 0000000..31adf96 --- /dev/null +++ b/src/uuid/compare.c @@ -0,0 +1,35 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2013 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// for already available uuid functionality +#include + +#include "class.h" +#include "uuid.h" + +int +uuidCompare(Uuid uuid1, Uuid uuid2) +{ + return uuid_compare((uuid1->uuid).value, (uuid2->uuid).value); +} + +// vim: set ts=4 sw=4: diff --git a/src/uuid/parse.c b/src/uuid/parse.c new file mode 100644 index 0000000..69d12a7 --- /dev/null +++ b/src/uuid/parse.c @@ -0,0 +1,38 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2013 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// for already available uuid functionality +#include + +#include "class.h" +#include "uuid.h" + +Uuid +uuidParse(const UuidString uuid_str) +{ + Uuid uuid = new(Uuid); + uuid_parse(uuid_str, (uuid->uuid).value); + + return uuid; +} + +// vim: set ts=4 sw=4: diff --git a/src/uuid/unparse.c b/src/uuid/unparse.c new file mode 100644 index 0000000..11623b5 --- /dev/null +++ b/src/uuid/unparse.c @@ -0,0 +1,35 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2013 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// for already available uuid functionality +#include + +#include "class.h" +#include "uuid.h" + +void +uuidUnparse(Uuid uuid, UuidString uuid_str) +{ + uuid_unparse((uuid->uuid).value, uuid_str); +} + +// vim: set ts=4 sw=4: diff --git a/src/uuid/uuid.c b/src/uuid/uuid.c new file mode 100644 index 0000000..374833d --- /dev/null +++ b/src/uuid/uuid.c @@ -0,0 +1,56 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2013 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "class.h" +#include "uuid.h" + + +static +int +uuidCtor(void * _this, va_list * params) +{ + return 0; +} + +static +void +uuidDtor(void * _this) +{ +} + +static +void +uuidClone(void * _this, void * _base) +{ + Uuid this = _this; + Uuid base = _base; + + memcpy((this->uuid).value, (base->uuid).value, 16); +} + +INIT_IFACE(Class, uuidCtor, uuidDtor, uuidClone); +CREATE_CLASS(Uuid, NULL, IFACE(Class)); + +// vim: set ts=4 sw=4: diff --git a/src/uuid/version1.c b/src/uuid/version1.c new file mode 100644 index 0000000..3da4438 --- /dev/null +++ b/src/uuid/version1.c @@ -0,0 +1,38 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2013 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// for already available uuid functionality +#include + +#include "class.h" +#include "uuid.h" + +Uuid +uuidVersion1() +{ + Uuid uuid = new(Uuid); + uuid_generate((uuid->uuid).value); + + return uuid; +} + +// vim: set ts=4 sw=4: diff --git a/src/uuid/version3.c b/src/uuid/version3.c new file mode 100644 index 0000000..3033fa2 --- /dev/null +++ b/src/uuid/version3.c @@ -0,0 +1,69 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2013 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// for size_t +#include + +// for md5 generation +#include + +// for htonl and similar +#include + +// for already available uuid functionality +#include "class.h" +#include "uuid.h" + +void _uuidFormat3or5(Uuid uuid, unsigned char hash[16], int version); + +Uuid +uuidVersion3(const unsigned char * name, size_t nname, Uuid nsid) +{ + MD5_CTX ctx; + unsigned char hash[16]; + Uuid net_nsid = clone(nsid); + Uuid uuid = new(Uuid); + + /* + * put the namespace id into network byte order. + */ + (net_nsid->uuid).elements.time_low = + htonl((net_nsid->uuid).elements.time_low); + (net_nsid->uuid).elements.time_mid = + htons((net_nsid->uuid).elements.time_mid); + (net_nsid->uuid).elements.time_hi_version = + htons((net_nsid->uuid).elements.time_hi_version); + + /* + * generate the MD5 + */ + MD5_Init(&ctx); + MD5_Update(&ctx, (net_nsid->uuid).value, 16); + MD5_Update(&ctx, name, nname); + MD5_Final(hash, &ctx); + + _uuidFormat3or5(uuid, hash, 3); + + return uuid; +} + +// vim: set ts=4 sw=4: diff --git a/src/uuid/version5.c b/src/uuid/version5.c new file mode 100644 index 0000000..2fb4d6f --- /dev/null +++ b/src/uuid/version5.c @@ -0,0 +1,69 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2013 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// for size_t +#include + +// for sha1 generation +#include + +// for htonl and similar +#include + +// for already available uuid functionality +#include "class.h" +#include "uuid.h" + +void _uuidFormat3or5(Uuid uuid, unsigned char hash[16], int version); + +Uuid +uuidVersion5(const unsigned char * name, size_t nname, Uuid nsid) +{ + SHA_CTX ctx; + unsigned char hash[20]; + Uuid net_nsid = clone(nsid); + Uuid uuid = new(Uuid); + + /* + * put the namespace id into network byte order. + */ + (net_nsid->uuid).elements.time_low = + htonl((net_nsid->uuid).elements.time_low); + (net_nsid->uuid).elements.time_mid = + htons((net_nsid->uuid).elements.time_mid); + (net_nsid->uuid).elements.time_hi_version = + htons((net_nsid->uuid).elements.time_hi_version); + + /* + * generate the MD5 + */ + SHA1_Init(&ctx); + SHA1_Update(&ctx, (net_nsid->uuid).value, 16); + SHA1_Update(&ctx, name, nname); + SHA1_Final(hash, &ctx); + + _uuidFormat3or5(uuid, hash, 5); + + return uuid; +} + +// vim: set ts=4 sw=4: