6 * Copyright (C) 2008-2015 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <glib/gprintf.h>
29 #include "sipe-digest.h"
32 #define UUID_STRING_LENGTH 36
33 static const char *epid_ns_uuid
= "fcacfb03-8a73-46ef-91b1-e5ebeeaba4fe";
36 * This assumes that the structure is correctly packed on all target
37 * platforms, i.e. sizeof(uuid_t) == 16
39 * See also the test added to "configure". On Windows platform we know
40 * that #pragma pack() exists and therefore can use it in the code.
49 guint16 time_hi_and_version
;
50 guint8 clock_seq_hi_and_reserved
;
58 #define UUID_OFFSET_TO_LAST_SEGMENT 24
60 static void readUUID(const char *string
, uuid_t
*uuid
)
63 /* Some platforms don't allow scanning to char using %02hhx */
66 sscanf(string
, "%08x-%04hx-%04hx-%02hx%02hx-", &uuid
->time_low
67 , &uuid
->time_mid
, &uuid
->time_hi_and_version
69 uuid
->clock_seq_hi_and_reserved
= tmp1
;
70 uuid
->clock_seq_low
= tmp2
;
74 sscanf(&string
[UUID_OFFSET_TO_LAST_SEGMENT
+i
*2], "%02hx", &tmp1
);
79 static void printUUID(uuid_t
*uuid
, char *string
)
83 sprintf(string
, "%08x-%04x-%04x-%02x%02x-", uuid
->time_low
84 , uuid
->time_mid
, uuid
->time_hi_and_version
85 , uuid
->clock_seq_hi_and_reserved
91 pos
+= sprintf(&string
[pos
], "%02x", uuid
->node
[i
]);
95 static void createUUIDfromHash(uuid_t
*uuid
, const unsigned char *hash
)
97 memcpy(uuid
, hash
, sizeof(uuid_t
));
98 uuid
->time_hi_and_version
&= GUINT16_TO_LE(0x0FFF);
99 uuid
->time_hi_and_version
|= GUINT16_TO_LE(0x5000);
100 uuid
->clock_seq_hi_and_reserved
&= 0x3F;
101 uuid
->clock_seq_hi_and_reserved
|= 0x80;
104 char *generateUUIDfromEPID(const gchar
*epid
)
108 guchar digest
[SIPE_DIGEST_SHA1_LENGTH
];
109 uint digest_length
= sizeof(uuid_t
) + strlen(epid
);
110 uint buf_length
= digest_length
;
112 readUUID(epid_ns_uuid
, &result
);
114 result
.time_low
= GUINT32_FROM_LE(result
.time_low
);
115 result
.time_mid
= GUINT16_FROM_LE(result
.time_mid
);
116 result
.time_hi_and_version
= GUINT16_FROM_LE(result
.time_hi_and_version
);
118 /* buffer must be able to hold at least the UUID string */
119 if (buf_length
< UUID_STRING_LENGTH
)
120 buf_length
= UUID_STRING_LENGTH
;
121 buf
= g_malloc(buf_length
+ 1);
123 memcpy(buf
, &result
, sizeof(uuid_t
));
124 strcpy(buf
+ sizeof(uuid_t
), epid
);
126 sipe_digest_sha1((guchar
*)buf
, digest_length
, digest
);
127 createUUIDfromHash(&result
, digest
);
129 result
.time_low
= GUINT32_TO_LE(result
.time_low
);
130 result
.time_mid
= GUINT16_TO_LE(result
.time_mid
);
131 result
.time_hi_and_version
= GUINT16_TO_LE(result
.time_hi_and_version
);
133 printUUID(&result
, buf
);
138 * Generates epid from user SIP URI, hostname and IP address.
139 * Thus epid will be the same each start and
140 * not needed to be persistent.
142 * Using MAC address proved to be poorly portable solution.
146 char *sipe_get_epid(const char *self_sip_uri
,
147 const char *hostname
,
148 const char *ip_address
)
150 /* 6 last digits of hash */
151 #define SIPE_EPID_HASH_START 14
152 #define SIPE_EPID_HASH_END SIPE_DIGEST_SHA1_LENGTH
153 #define SIPE_EPID_LENGTH (2 * (SIPE_EPID_HASH_END - SIPE_EPID_HASH_START + 1))
156 char out
[SIPE_EPID_LENGTH
+ 1];
157 char *buf
= g_strdup_printf("%s:%s:%s", self_sip_uri
, hostname
, ip_address
);
158 guchar hash
[SIPE_DIGEST_SHA1_LENGTH
];
160 sipe_digest_sha1((guchar
*) buf
, strlen(buf
), hash
);
161 for (i
= SIPE_EPID_HASH_START
, j
= 0;
162 i
< SIPE_EPID_HASH_END
;
164 g_sprintf(&out
[j
], "%02x", hash
[i
]);
166 out
[SIPE_EPID_LENGTH
] = 0;
169 return g_strdup(out
);