jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, 00004 * Ryan Eatmon, Robert Norris 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00019 */ 00020 00021 #include "util.h" 00022 #include <stringprep.h> 00023 00025 static jid_t jid_reset_components_internal(jid_t jid, const unsigned char *node, const unsigned char *domain, const unsigned char *resource, int prepare); 00026 00028 static int jid_prep_pieces(char *node, char *domain, char *resource) { 00029 if(node[0] != '\0') 00030 if(stringprep_xmpp_nodeprep(node, 1024) != 0) 00031 return 1; 00032 00033 if(stringprep_nameprep(domain, 1024) != 0) 00034 return 1; 00035 00036 if(resource[0] != '\0') 00037 if(stringprep_xmpp_resourceprep(resource, 1024) != 0) 00038 return 1; 00039 00040 return 0; 00041 } 00042 00044 int jid_prep(jid_t jid) 00045 { 00046 char node[MAXLEN_JID_COMP+1]; 00047 char domain[MAXLEN_JID_COMP+1]; 00048 char resource[MAXLEN_JID_COMP+1]; 00049 00050 if(jid->node != NULL) { 00051 strncpy(node, jid->node, MAXLEN_JID_COMP); 00052 node[MAXLEN_JID_COMP]='\0'; 00053 } 00054 else 00055 node[0] = '\0'; 00056 00057 if(jid->domain != NULL) { 00058 strncpy(domain, jid->domain, MAXLEN_JID_COMP); 00059 domain[MAXLEN_JID_COMP]='\0'; 00060 } 00061 else 00062 domain[0] = '\0'; 00063 00064 if(jid->resource != NULL) { 00065 strncpy(resource, jid->resource, MAXLEN_JID_COMP); 00066 resource[MAXLEN_JID_COMP]='\0'; 00067 } 00068 else 00069 resource[0] = '\0'; 00070 00071 if(jid_prep_pieces(node, domain, resource) != 0) 00072 return 1; 00073 00074 /* put prepared components into jid */ 00075 jid_reset_components_internal(jid, node, domain, resource, 0); 00076 00077 return 0; 00078 } 00079 00081 jid_t jid_new(const unsigned char *id, int len) { 00082 jid_t jid, ret; 00083 00084 jid = malloc(sizeof(struct jid_st)); 00085 jid->jid_data = NULL; 00086 00087 ret = jid_reset(jid, id, len); 00088 if(ret == NULL) { 00089 if(len < 0) { 00090 log_debug(ZONE, "invalid jid: %s", id); 00091 } else { 00092 log_debug(ZONE, "invalid jid: %.*s", len, id); 00093 } 00094 free(jid); 00095 } 00096 00097 return ret; 00098 } 00099 00102 void jid_static(jid_t jid, jid_static_buf *buf) 00103 { 00104 /* clear jid */ 00105 memset(jid, 0, sizeof(*jid)); 00106 00107 /* set buffer */ 00108 jid->jid_data = (unsigned char *)buf; 00109 } 00110 00111 00113 jid_t jid_reset(jid_t jid, const unsigned char *id, int len) { 00114 unsigned char *myid, *cur, *olddata=NULL; 00115 00116 assert((int) (jid != NULL)); 00117 00118 if (jid->jid_data != NULL) { 00119 if(jid->jid_data_len != 0) 00120 free(jid->jid_data); 00121 else 00122 olddata = jid->jid_data; /* store pointer to old data */ 00123 } 00124 memset(jid, 0, sizeof(struct jid_st)); 00125 jid->dirty = 1; 00126 jid->node = ""; 00127 jid->domain = ""; 00128 jid->resource = ""; 00129 00130 /* nice empty jid */ 00131 if(id == NULL) 00132 return jid; 00133 00134 if(len < 0) 00135 len = strlen(id); 00136 00137 if((len == 0) || (len > MAXLEN_JID)) 00138 return NULL; 00139 00140 if(olddata != NULL) 00141 myid = olddata; /* use static buffer */ 00142 else { 00143 jid->jid_data_len = sizeof(char) * (len + 1); 00144 myid = (char *) malloc(jid->jid_data_len); 00145 } 00146 sprintf(myid, "%.*s", len, id); 00147 00148 /* fail - only a resource or leading @ */ 00149 if(myid[0] == '/' || myid[0] == '@') { 00150 if(olddata == NULL) free(myid); 00151 return NULL; 00152 } 00153 00154 /* get the resource first */ 00155 cur = strstr(myid, "/"); 00156 00157 if(cur != NULL) 00158 { 00159 *cur = '\0'; 00160 cur++; 00161 if(strlen(cur) > 0) { 00162 jid->resource = cur; 00163 } else { 00164 /* fail - a resource separator but nothing after it */ 00165 if(olddata == NULL) free(myid); 00166 return NULL; 00167 } 00168 } 00169 00170 /* find the domain */ 00171 cur = strstr(myid, "@"); 00172 if(cur != NULL) { 00173 *cur = '\0'; 00174 cur++; 00175 if(strlen(cur) == 0) { 00176 /* no domain part, bail out */ 00177 if(olddata == NULL) free(myid); 00178 return NULL; 00179 } 00180 jid->domain = cur; 00181 jid->node = myid; 00182 } else { 00183 /* no @, so it's a domain only */ 00184 jid->domain = myid; 00185 } 00186 00187 jid->jid_data = myid; 00188 00189 if(jid_prep(jid) != 0) { 00190 if(olddata == NULL) free(myid); 00191 jid->jid_data = NULL; 00192 return NULL; 00193 } 00194 00195 return jid; 00196 } 00197 00199 static jid_t jid_reset_components_internal(jid_t jid, const unsigned char *node, const unsigned char *domain, const unsigned char *resource, int prepare) { 00200 unsigned char *olddata=NULL; 00201 int node_l,domain_l,resource_l; 00202 int dataStatic; 00203 jid_static_buf staticTmpBuf; 00204 00205 assert((int) (jid != NULL)); 00206 00207 if(jid->jid_data != NULL) 00208 olddata = jid->jid_data; /* Store old data before clearing JID */ 00209 00210 dataStatic = ((jid->jid_data != NULL) && (jid->jid_data_len == 0)); 00211 00212 if (jid->_user != NULL ) 00213 free(jid->_user); 00214 if (jid->_full != NULL ) 00215 free(jid->_full); 00216 00217 memset(jid, 0, sizeof(struct jid_st)); 00218 00219 /* get lengths */ 00220 node_l = strlen(node); 00221 domain_l = strlen(domain); 00222 resource_l = strlen(resource); 00223 00224 if(node_l > MAXLEN_JID_COMP) 00225 node_l = MAXLEN_JID_COMP; 00226 00227 if(domain_l > MAXLEN_JID_COMP) 00228 domain_l = MAXLEN_JID_COMP; 00229 00230 if(resource_l > MAXLEN_JID_COMP) 00231 resource_l = MAXLEN_JID_COMP; 00232 00233 if(dataStatic) { 00234 /* use static buffer */ 00235 jid->jid_data = staticTmpBuf; 00236 } 00237 else { 00238 /* allocate new data buffer */ 00239 jid->jid_data_len = node_l+domain_l+resource_l+3; 00240 jid->jid_data = realloc(jid->jid_data, jid->jid_data_len); 00241 } 00242 00243 /* copy to buffer */ 00244 jid->node = jid->jid_data; 00245 strncpy(jid->node, node, node_l); 00246 jid->node[node_l] = 0; 00247 00248 jid->domain = jid->node + node_l + 1; 00249 strncpy(jid->domain, domain, domain_l); 00250 jid->domain[domain_l] = 0; 00251 00252 jid->resource = jid->domain + domain_l + 1; 00253 strncpy(jid->resource, resource, resource_l); 00254 jid->resource[resource_l] = 0; 00255 00256 /* Free old data buffer. Postponed to this point so that arguments may point (in)to old jid data. */ 00257 if((!dataStatic) && (olddata != NULL)) 00258 free(olddata); 00259 00260 if(prepare) { 00261 if(jid_prep(jid) != 0) 00262 return NULL; 00263 } 00264 00265 jid->dirty = 1; 00266 00267 if (dataStatic) { 00268 jid->jid_data = olddata; /* Return pointer to the original static buffer */ 00269 memcpy(jid->jid_data,staticTmpBuf,node_l+domain_l+resource_l+3); /* Copy data from tmp buf to original buffer */ 00270 00271 /* Relocate pointers */ 00272 jid->node = olddata+(jid->node-(unsigned char *)staticTmpBuf); 00273 jid->domain = olddata+(jid->domain-(unsigned char *)staticTmpBuf); 00274 jid->resource = olddata+(jid->resource-(unsigned char *)staticTmpBuf); 00275 } 00276 00277 return jid; 00278 } 00279 00281 jid_t jid_reset_components(jid_t jid, const unsigned char *node, const unsigned char *domain, const unsigned char *resource) { 00282 return jid_reset_components_internal(jid, node, domain, resource, 1); 00283 } 00284 00286 void jid_free(jid_t jid) 00287 { 00288 if((jid->jid_data != NULL) && (jid->jid_data_len != 0)) 00289 free(jid->jid_data); 00290 if (jid->_user != NULL ) 00291 free(jid->_user); 00292 if (jid->_full != NULL ) 00293 free(jid->_full); 00294 if (jid != NULL ) 00295 free(jid); 00296 } 00297 00299 void jid_expand(jid_t jid) 00300 { 00301 int nlen, dlen, rlen, ulen; 00302 00303 if((!jid->dirty) && (jid->_full)) 00304 return; /* Not dirty & already expanded */ 00305 00306 if(*jid->domain == '\0') { 00307 /* empty */ 00308 jid->_full = (unsigned char*) realloc(jid->_full, 1); 00309 jid->_full[0] = 0; 00310 return; 00311 } 00312 00313 nlen = strlen(jid->node); 00314 dlen = strlen(jid->domain); 00315 rlen = strlen(jid->resource); 00316 00317 if(nlen == 0) { 00318 ulen = dlen+1; 00319 jid->_user = (unsigned char*) realloc(jid->_user, ulen); 00320 strcpy(jid->_user, jid->domain); 00321 } else { 00322 ulen = nlen+1+dlen+1; 00323 jid->_user = (unsigned char*) realloc(jid->_user, ulen); 00324 snprintf(jid->_user, ulen, "%s@%s", jid->node, jid->domain); 00325 } 00326 00327 if(rlen == 0) { 00328 jid->_full = (unsigned char*) realloc(jid->_full, ulen); 00329 strcpy(jid->_full, jid->_user); 00330 } else { 00331 jid->_full = (unsigned char*) realloc(jid->_full, ulen+1+rlen); 00332 snprintf(jid->_full, ulen+1+rlen, "%s/%s", jid->_user, jid->resource); 00333 } 00334 00335 jid->dirty = 0; 00336 } 00337 00339 const unsigned char *jid_user(jid_t jid) 00340 { 00341 jid_expand(jid); 00342 00343 return jid->_user; 00344 } 00345 00347 const unsigned char *jid_full(jid_t jid) 00348 { 00349 jid_expand(jid); 00350 00351 return jid->_full; 00352 } 00353 00355 int jid_compare_user(jid_t a, jid_t b) 00356 { 00357 jid_expand(a); 00358 jid_expand(b); 00359 00360 return strcmp(a->_user, b->_user); 00361 } 00362 00364 int jid_compare_full(jid_t a, jid_t b) 00365 { 00366 jid_expand(a); 00367 jid_expand(b); 00368 00369 return strcmp(a->_full, b->_full); 00370 } 00371 00373 jid_t jid_dup(jid_t jid) 00374 { 00375 jid_t new; 00376 00377 new = (jid_t) malloc(sizeof(struct jid_st)); 00378 memcpy(new, jid, sizeof(struct jid_st)); 00379 if(jid->jid_data != NULL) { 00380 if(jid->jid_data_len == 0) { 00381 /* when original jid had static buffer, allocate new dynamic buffer 00382 * of the same size as has the static buffer */ 00383 jid->jid_data_len = sizeof(jid_static_buf); 00384 } 00385 00386 /* allocate & populate new dynamic buffer */ 00387 new->jid_data = malloc(new->jid_data_len); 00388 memcpy(new->jid_data, jid->jid_data, new->jid_data_len); 00389 00390 /* relocate pointers */ 00391 if(jid->node[0] == '\0') 00392 new->node = ""; 00393 else 00394 new->node = new->jid_data + (jid->node - jid->jid_data); 00395 if(jid->domain[0] == '\0') 00396 new->domain = ""; 00397 else 00398 new->domain = new->jid_data + (jid->domain - jid->jid_data); 00399 if(jid->resource[0] == '\0') 00400 new->resource = ""; 00401 else 00402 new->resource = new->jid_data + (jid->resource - jid->jid_data); 00403 } 00404 if(jid->_user) 00405 new->_user = strdup(jid->_user); 00406 if(jid->_full) 00407 new->_full = strdup(jid->_full); 00408 00409 return new; 00410 } 00411 00413 int jid_search(jid_t list, jid_t jid) 00414 { 00415 jid_t cur; 00416 for(cur = list; cur != NULL; cur = cur->next) 00417 if(jid_compare_full(cur,jid) == 0) 00418 return 1; 00419 return 0; 00420 } 00421 00423 jid_t jid_zap(jid_t list, jid_t jid) 00424 { 00425 jid_t cur, dead; 00426 00427 if(jid == NULL || list == NULL) 00428 return NULL; 00429 00430 /* check first */ 00431 if(jid_compare_full(jid,list) == 0) { 00432 cur = list->next; 00433 jid_free(list); 00434 return cur; 00435 } 00436 00437 /* check through the list, stopping at the previous list entry to a matching one */ 00438 cur = list; 00439 while(cur != NULL) 00440 { 00441 if(cur->next == NULL) 00442 /* none match, so we're done */ 00443 return list; 00444 00445 if(jid_compare_full(cur->next, jid) == 0) 00446 { 00447 /* match, kill it */ 00448 dead = cur->next; 00449 cur->next = cur->next->next; 00450 jid_free(dead); 00451 00452 return list; 00453 } 00454 00455 /* loop */ 00456 cur = cur->next; 00457 } 00458 00459 /* shouldn't get here */ 00460 return list; 00461 } 00462 00464 jid_t jid_append(jid_t list, jid_t jid) 00465 { 00466 jid_t scan; 00467 00468 if(list == NULL) 00469 return jid_dup(jid); 00470 00471 scan = list; 00472 while(scan != NULL) 00473 { 00474 /* check for dups */ 00475 if(jid_compare_full(scan, jid) == 0) 00476 return list; 00477 00478 /* tack it on to the end of the list */ 00479 if(scan->next == NULL) 00480 { 00481 scan->next = jid_dup(jid); 00482 return list; 00483 } 00484 00485 scan = scan->next; 00486 } 00487 00488 return list; 00489 } 00490 00492 void jid_random_part(jid_t jid, jid_part_t part) 00493 { 00494 char hashBuf[41]; 00495 char randomBuf[257]; 00496 int i,r; 00497 00498 /* create random string */ 00499 for(i = 0; i < 256; i++) { 00500 r = (int) (36.0 * rand() / RAND_MAX); 00501 randomBuf[i] = (r >= 0 && r <= 0) ? (r + 48) : (r + 87); 00502 } 00503 randomBuf[256] = 0; 00504 00505 /* hash it */ 00506 shahash_r(randomBuf, hashBuf); 00507 00508 /* change jid */ 00509 switch(part) { 00510 case jid_NODE: 00511 jid_reset_components(jid, hashBuf, jid->domain, jid->resource); 00512 break; 00513 00514 case jid_DOMAIN: /* unused */ 00515 jid_reset_components(jid, jid->node, hashBuf, jid->resource); 00516 break; 00517 00518 case jid_RESOURCE: 00519 jid_reset_components(jid, jid->node, jid->domain, hashBuf); 00520 break; 00521 } 00522 00523 /* prepare */ 00524 jid_prep(jid); 00525 } 00526