core cleanup: 6 more modules are purple free
[siplcs.git] / src / core / uuid.c
blob1fa5836b91199ae1038e4df9300ef686ef687a04
1 /**
2 * @file uuid.c
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdio.h>
20 #include <string.h>
22 #include <cipher.h>
23 #include <glib.h>
24 #include <glib/gprintf.h>
26 #include "uuid.h"
28 static const char *epid_ns_uuid = "fcacfb03-8a73-46ef-91b1-e5ebeeaba4fe";
31 * This assumes that the structure is correctly packed on all target
32 * platforms, i.e. sizeof(uuid_t) == 16
34 * See also the test added to "configure". On Windows platform we know
35 * that #pragma pack() exists and therefore can use it in the code.
38 #ifdef _WIN32
39 #pragma pack(push, 1)
40 #endif
41 typedef struct {
42 guint32 time_low;
43 guint16 time_mid;
44 guint16 time_hi_and_version;
45 guint8 clock_seq_hi_and_reserved;
46 guint8 clock_seq_low;
47 guint8 node[6];
48 } uuid_t;
49 #ifdef _WIN32
50 #pragma pack(pop)
51 #endif
53 #define UUID_OFFSET_TO_LAST_SEGMENT 24
55 static void readUUID(const char *string, uuid_t *uuid)
57 int i;
58 /* Some platforms don't allow scanning to char using %02hhx */
59 short tmp1, tmp2;
61 sscanf(string, "%08x-%04hx-%04hx-%02hx%02hx-", &uuid->time_low
62 , &uuid->time_mid, &uuid->time_hi_and_version
63 , &tmp1, &tmp2);
64 uuid->clock_seq_hi_and_reserved = tmp1;
65 uuid->clock_seq_low = tmp2;
67 for(i=0;i<6;i++)
69 sscanf(&string[UUID_OFFSET_TO_LAST_SEGMENT+i*2], "%02hx", &tmp1);
70 uuid->node[i] = tmp1;
74 static void printUUID(uuid_t *uuid, char *string)
76 int i;
77 size_t pos;
78 sprintf(string, "%08x-%04x-%04x-%02x%02x-", uuid->time_low
79 , uuid->time_mid, uuid->time_hi_and_version
80 , uuid->clock_seq_hi_and_reserved
81 , uuid->clock_seq_low
83 pos = strlen(string);
84 for(i=0;i<6;i++)
86 pos += sprintf(&string[pos], "%02x", uuid->node[i]);
90 static void createUUIDfromHash(uuid_t *uuid, const unsigned char *hash)
92 memcpy(uuid, hash, sizeof(uuid_t));
93 uuid->time_hi_and_version &= GUINT16_TO_LE(0x0FFF);
94 uuid->time_hi_and_version |= GUINT16_TO_LE(0x5000);
95 uuid->clock_seq_hi_and_reserved &= 0x3F;
96 uuid->clock_seq_hi_and_reserved |= 0x80;
99 char *generateUUIDfromEPID(const gchar *epid)
101 uuid_t result;
102 PurpleCipherContext *ctx;
103 unsigned char hash[20];
104 char buf[512];
106 readUUID(epid_ns_uuid, &result);
108 result.time_low = GUINT32_FROM_LE(result.time_low);
109 result.time_mid = GUINT16_FROM_LE(result.time_mid);
110 result.time_hi_and_version = GUINT16_FROM_LE(result.time_hi_and_version);
112 memcpy(buf, &result, sizeof(uuid_t));
113 strcpy(&buf[sizeof(uuid_t)], epid);
115 ctx = purple_cipher_context_new_by_name("sha1", NULL);
116 purple_cipher_context_append(ctx, (guchar *) buf, strlen(buf));
117 purple_cipher_context_digest(ctx, sizeof(hash), hash, NULL);
118 purple_cipher_context_destroy(ctx);
120 createUUIDfromHash(&result, hash);
122 result.time_low = GUINT32_TO_LE(result.time_low);
123 result.time_mid = GUINT16_TO_LE(result.time_mid);
124 result.time_hi_and_version = GUINT16_TO_LE(result.time_hi_and_version);
126 printUUID(&result, buf);
127 return g_strdup(buf);
131 * Generates epid from user SIP URI, hostname and IP address.
132 * Thus epid will be the same each start and
133 * not needed to be persistent.
135 * Using MAC address proved to be poorly portable solution.
137 * Must be g_free()'d
139 char *sipe_get_epid(const char *self_sip_uri,
140 const char *hostname,
141 const char *ip_address)
143 /* 6 last digits of hash */
144 #define SIPE_EPID_HASH_START 14
145 #define SIPE_EPID_HASH_END 20
146 #define SIPE_EPID_LENGTH (2 * (SIPE_EPID_HASH_END - SIPE_EPID_HASH_START + 1))
148 int i,j;
149 PurpleCipherContext *ctx;
150 unsigned char hash[SIPE_EPID_HASH_END];
151 char out[SIPE_EPID_LENGTH + 1];
152 char *buf = g_strdup_printf("%s:%s:%s", self_sip_uri, hostname, ip_address);
154 ctx = purple_cipher_context_new_by_name("sha1", NULL);
155 purple_cipher_context_append(ctx, (guchar *)buf, strlen(buf));
156 purple_cipher_context_digest(ctx, sizeof(hash), hash, NULL);
157 purple_cipher_context_destroy(ctx);
159 for (i = SIPE_EPID_HASH_START, j = 0;
160 i < SIPE_EPID_HASH_END;
161 i++, j += 2) {
162 g_sprintf(&out[j], "%02x", hash[i]);
164 out[SIPE_EPID_LENGTH] = 0;
166 g_free(buf);
167 return g_strdup(out);
171 Local Variables:
172 mode: c
173 c-file-style: "bsd"
174 indent-tabs-mode: t
175 tab-width: 8
176 End: