1 /**
2 * @file src/account.c User-Agent account
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6 #include <string.h>
7 #include <re.h>
8 #include <baresip.h>
9 #include "core.h"
10
11
12 enum {
13 REG_INTERVAL = 3600,
14 };
15
16
destructor(void * arg)17 static void destructor(void *arg)
18 {
19 struct account *acc = arg;
20 size_t i;
21
22 list_clear(&acc->aucodecl);
23 list_clear(&acc->vidcodecl);
24 mem_deref(acc->auth_user);
25 mem_deref(acc->auth_pass);
26 for (i=0; i<ARRAY_SIZE(acc->outboundv); i++)
27 mem_deref(acc->outboundv[i]);
28 mem_deref(acc->regq);
29 mem_deref(acc->rtpkeep);
30 mem_deref(acc->sipnat);
31 mem_deref(acc->stun_user);
32 mem_deref(acc->stun_pass);
33 mem_deref(acc->stun_host);
34 mem_deref(acc->mnatid);
35 mem_deref(acc->mencid);
36 mem_deref(acc->aor);
37 mem_deref(acc->dispname);
38 mem_deref(acc->buf);
39 }
40
41
param_dstr(char ** dstr,const struct pl * params,const char * name)42 static int param_dstr(char **dstr, const struct pl *params, const char *name)
43 {
44 struct pl pl;
45
46 if (msg_param_decode(params, name, &pl))
47 return 0;
48
49 return pl_strdup(dstr, &pl);
50 }
51
52
param_u32(uint32_t * v,const struct pl * params,const char * name)53 static int param_u32(uint32_t *v, const struct pl *params, const char *name)
54 {
55 struct pl pl;
56
57 if (msg_param_decode(params, name, &pl))
58 return 0;
59
60 *v = pl_u32(&pl);
61
62 return 0;
63 }
64
65
66 /*
67 * Decode STUN parameters, inspired by RFC 7064
68 *
69 * See RFC 3986:
70 *
71 * Use of the format "user:password" in the userinfo field is
72 * deprecated.
73 *
74 */
stunsrv_decode(struct account * acc,const struct sip_addr * aor)75 static int stunsrv_decode(struct account *acc, const struct sip_addr *aor)
76 {
77 struct pl srv, tmp;
78 struct uri uri;
79 int err;
80
81 if (!acc || !aor)
82 return EINVAL;
83
84 memset(&uri, 0, sizeof(uri));
85
86 if (0 == msg_param_decode(&aor->params, "stunserver", &srv)) {
87
88 info("using stunserver: '%r'\n", &srv);
89
90 err = uri_decode(&uri, &srv);
91 if (err) {
92 warning("account: %r: decode failed: %m\n", &srv, err);
93 memset(&uri, 0, sizeof(uri));
94 }
95
96 if (0 != pl_strcasecmp(&uri.scheme, "stun")) {
97 warning("account: unknown scheme: %r\n", &uri.scheme);
98 return EINVAL;
99 }
100 }
101
102 err = 0;
103
104 if (0 == msg_param_exists(&aor->params, "stunuser", &tmp))
105 err |= param_dstr(&acc->stun_user, &aor->params, "stunuser");
106 else if (pl_isset(&uri.user))
107 err |= pl_strdup(&acc->stun_user, &uri.user);
108 else
109 err |= pl_strdup(&acc->stun_user, &aor->uri.user);
110
111 if (0 == msg_param_exists(&aor->params, "stunpass", &tmp))
112 err |= param_dstr(&acc->stun_pass, &aor->params, "stunpass");
113 else if (pl_isset(&uri.password))
114 err |= pl_strdup(&acc->stun_pass, &uri.password);
115 else if (acc->auth_pass)
116 err |= str_dup(&acc->stun_pass, acc->auth_pass);
117
118 if (pl_isset(&uri.host))
119 err |= pl_strdup(&acc->stun_host, &uri.host);
120 else
121 err |= pl_strdup(&acc->stun_host, &aor->uri.host);
122
123 acc->stun_port = uri.port;
124
125 return err;
126 }
127
128
129 /** Decode media parameters */
media_decode(struct account * acc,const struct pl * prm)130 static int media_decode(struct account *acc, const struct pl *prm)
131 {
132 int err = 0;
133
134 if (!acc || !prm)
135 return EINVAL;
136
137 err |= param_dstr(&acc->mencid, prm, "mediaenc");
138 err |= param_dstr(&acc->mnatid, prm, "medianat");
139 err |= param_dstr(&acc->rtpkeep, prm, "rtpkeep" );
140 err |= param_u32(&acc->ptime, prm, "ptime" );
141
142 return err;
143 }
144
145
146 /* Decode answermode parameter */
answermode_decode(struct account * prm,const struct pl * pl)147 static void answermode_decode(struct account *prm, const struct pl *pl)
148 {
149 struct pl amode;
150
151 if (0 == msg_param_decode(pl, "answermode", &amode)) {
152
153 if (0 == pl_strcasecmp(&amode, "manual")) {
154 prm->answermode = ANSWERMODE_MANUAL;
155 }
156 else if (0 == pl_strcasecmp(&amode, "early")) {
157 prm->answermode = ANSWERMODE_EARLY;
158 }
159 else if (0 == pl_strcasecmp(&amode, "auto")) {
160 prm->answermode = ANSWERMODE_AUTO;
161 }
162 else {
163 warning("account: answermode unknown (%r)\n", &amode);
164 prm->answermode = ANSWERMODE_MANUAL;
165 }
166 }
167 }
168
169
csl_parse(struct pl * pl,char * str,size_t sz)170 static int csl_parse(struct pl *pl, char *str, size_t sz)
171 {
172 struct pl ws = PL_INIT, val, ws2 = PL_INIT, cma = PL_INIT;
173 int err;
174
175 err = re_regex(pl->p, pl->l, "[ \t]*[^, \t]+[ \t]*[,]*",
176 &ws, &val, &ws2, &cma);
177 if (err)
178 return err;
179
180 pl_advance(pl, ws.l + val.l + ws2.l + cma.l);
181
182 (void)pl_strcpy(&val, str, sz);
183
184 return 0;
185 }
186
187
audio_codecs_decode(struct account * acc,const struct pl * prm)188 static int audio_codecs_decode(struct account *acc, const struct pl *prm)
189 {
190 struct list *aucodecl = baresip_aucodecl();
191 struct pl tmp;
192
193 if (!acc || !prm)
194 return EINVAL;
195
196 list_init(&acc->aucodecl);
197
198 if (0 == msg_param_exists(prm, "audio_codecs", &tmp)) {
199 struct pl acs;
200 char cname[64];
201 unsigned i = 0;
202
203 if (msg_param_decode(prm, "audio_codecs", &acs))
204 return 0;
205
206 while (0 == csl_parse(&acs, cname, sizeof(cname))) {
207 struct aucodec *ac;
208 struct pl pl_cname, pl_srate, pl_ch = PL_INIT;
209 uint32_t srate = 8000;
210 uint8_t ch = 1;
211
212 /* Format: "codec/srate/ch" */
213 if (0 == re_regex(cname, str_len(cname),
214 "[^/]+/[0-9]+[/]*[0-9]*",
215 &pl_cname, &pl_srate,
216 NULL, &pl_ch)) {
217 (void)pl_strcpy(&pl_cname, cname,
218 sizeof(cname));
219 srate = pl_u32(&pl_srate);
220 if (pl_isset(&pl_ch))
221 ch = pl_u32(&pl_ch);
222 }
223
224 ac = (struct aucodec *)aucodec_find(aucodecl,
225 cname, srate, ch);
226 if (!ac) {
227 warning("account: audio codec not found:"
228 " %s/%u/%d\n",
229 cname, srate, ch);
230 continue;
231 }
232
233 /* NOTE: static list with references to aucodec */
234 list_append(&acc->aucodecl, &acc->acv[i++], ac);
235
236 if (i >= ARRAY_SIZE(acc->acv))
237 break;
238 }
239 }
240
241 return 0;
242 }
243
244
245 #ifdef USE_VIDEO
video_codecs_decode(struct account * acc,const struct pl * prm)246 static int video_codecs_decode(struct account *acc, const struct pl *prm)
247 {
248 struct list *vidcodecl = baresip_vidcodecl();
249 struct pl tmp;
250
251 if (!acc || !prm)
252 return EINVAL;
253
254 list_init(&acc->vidcodecl);
255
256 if (0 == msg_param_exists(prm, "video_codecs", &tmp)) {
257 struct pl vcs;
258 char cname[64];
259 unsigned i = 0;
260
261 if (msg_param_decode(prm, "video_codecs", &vcs))
262 return 0;
263
264 while (0 == csl_parse(&vcs, cname, sizeof(cname))) {
265 struct vidcodec *vc;
266
267 vc = (struct vidcodec *)vidcodec_find(vidcodecl,
268 cname, NULL);
269 if (!vc) {
270 warning("account: video codec not found: %s\n",
271 cname);
272 continue;
273 }
274
275 /* NOTE: static list with references to vidcodec */
276 list_append(&acc->vidcodecl, &acc->vcv[i++], vc);
277
278 if (i >= ARRAY_SIZE(acc->vcv))
279 break;
280 }
281 }
282
283 return 0;
284 }
285 #endif
286
287
sip_params_decode(struct account * acc,const struct sip_addr * aor)288 static int sip_params_decode(struct account *acc, const struct sip_addr *aor)
289 {
290 struct pl auth_user;
291 size_t i;
292 int err = 0;
293
294 if (!acc || !aor)
295 return EINVAL;
296
297 acc->regint = REG_INTERVAL + (rand_u32()&0xff);
298 err |= param_u32(&acc->regint, &aor->params, "regint");
299
300 acc->pubint = 0;
301 err |= param_u32(&acc->pubint, &aor->params, "pubint");
302
303 err |= param_dstr(&acc->regq, &aor->params, "regq");
304
305 for (i=0; i<ARRAY_SIZE(acc->outboundv); i++) {
306
307 char expr[16] = "outbound";
308
309 expr[8] = i + 1 + 0x30;
310 expr[9] = '\0';
311
312 err |= param_dstr(&acc->outboundv[i], &aor->params, expr);
313 }
314
315 /* backwards compat */
316 if (!acc->outboundv[0]) {
317 err |= param_dstr(&acc->outboundv[0], &aor->params,
318 "outbound");
319 }
320
321 err |= param_dstr(&acc->sipnat, &aor->params, "sipnat");
322
323 if (0 == msg_param_decode(&aor->params, "auth_user", &auth_user))
324 err |= pl_strdup(&acc->auth_user, &auth_user);
325 else
326 err |= pl_strdup(&acc->auth_user, &aor->uri.user);
327
328 if (pl_isset(&aor->dname))
329 err |= pl_strdup(&acc->dispname, &aor->dname);
330
331 return err;
332 }
333
334
encode_uri_user(struct re_printf * pf,const struct uri * uri)335 static int encode_uri_user(struct re_printf *pf, const struct uri *uri)
336 {
337 struct uri uuri = *uri;
338
339 uuri.password = uuri.params = uuri.headers = pl_null;
340
341 return uri_encode(pf, &uuri);
342 }
343
344
account_alloc(struct account ** accp,const char * sipaddr)345 int account_alloc(struct account **accp, const char *sipaddr)
346 {
347 struct account *acc;
348 struct pl pl;
349 int err = 0;
350
351 if (!accp || !sipaddr)
352 return EINVAL;
353
354 acc = mem_zalloc(sizeof(*acc), destructor);
355 if (!acc)
356 return ENOMEM;
357
358 err = str_dup(&acc->buf, sipaddr);
359 if (err)
360 goto out;
361
362 pl_set_str(&pl, acc->buf);
363 err = sip_addr_decode(&acc->laddr, &pl);
364 if (err) {
365 warning("account: error parsing SIP address: '%r'\n", &pl);
366 goto out;
367 }
368
369 acc->luri = acc->laddr.uri;
370 acc->luri.password = pl_null;
371
372 err = re_sdprintf(&acc->aor, "%H", encode_uri_user, &acc->luri);
373 if (err)
374 goto out;
375
376 /* Decode parameters */
377 acc->ptime = 20;
378 err |= sip_params_decode(acc, &acc->laddr);
379 answermode_decode(acc, &acc->laddr.params);
380 err |= audio_codecs_decode(acc, &acc->laddr.params);
381 #ifdef USE_VIDEO
382 err |= video_codecs_decode(acc, &acc->laddr.params);
383 #endif
384 err |= media_decode(acc, &acc->laddr.params);
385 if (err)
386 goto out;
387
388 /* optional password prompt */
389 if (pl_isset(&acc->laddr.uri.password)) {
390
391 warning("account: username:password is now deprecated"
392 " please use ;auth_pass=xxx instead\n");
393
394 err = re_sdprintf(&acc->auth_pass, "%H",
395 uri_password_unescape,
396 &acc->laddr.uri.password);
397 if (err)
398 goto out;
399 }
400 else if (0 == msg_param_decode(&acc->laddr.params, "auth_pass", &pl)) {
401 err = pl_strdup(&acc->auth_pass, &pl);
402 if (err)
403 goto out;
404 }
405
406 err = stunsrv_decode(acc, &acc->laddr);
407 if (err)
408 goto out;
409
410 if (acc->mnatid) {
411 acc->mnat = mnat_find(baresip_mnatl(), acc->mnatid);
412 if (!acc->mnat) {
413 warning("account: medianat not found: `%s'\n",
414 acc->mnatid);
415 }
416 }
417
418 if (acc->mencid) {
419 acc->menc = menc_find(baresip_mencl(), acc->mencid);
420 if (!acc->menc) {
421 warning("account: mediaenc not found: `%s'\n",
422 acc->mencid);
423 }
424 }
425
426 out:
427 if (err)
428 mem_deref(acc);
429 else
430 *accp = acc;
431
432 return err;
433 }
434
435
account_set_auth_pass(struct account * acc,const char * pass)436 int account_set_auth_pass(struct account *acc, const char *pass)
437 {
438 if (!acc)
439 return EINVAL;
440
441 acc->auth_pass = mem_deref(acc->auth_pass);
442
443 if (pass)
444 return str_dup(&acc->auth_pass, pass);
445
446 return 0;
447 }
448
449
450 /**
451 * Sets the displayed name. Pass null in dname to disable display name
452 *
453 * @param acc User-Agent account
454 * @param dname Display name (NULL to disable)
455 *
456 * @return 0 if success, otherwise errorcode
457 */
account_set_display_name(struct account * acc,const char * dname)458 int account_set_display_name(struct account *acc, const char *dname)
459 {
460 if (!acc)
461 return EINVAL;
462
463 acc->dispname = mem_deref(acc->dispname);
464
465 if (dname)
466 return str_dup(&acc->dispname, dname);
467
468 return 0;
469 }
470
471
472 /**
473 * Authenticate a User-Agent (UA)
474 *
475 * @param acc User-Agent account
476 * @param username Pointer to allocated username string
477 * @param password Pointer to allocated password string
478 * @param realm Realm string
479 *
480 * @return 0 if success, otherwise errorcode
481 */
account_auth(const struct account * acc,char ** username,char ** password,const char * realm)482 int account_auth(const struct account *acc, char **username, char **password,
483 const char *realm)
484 {
485 if (!acc)
486 return EINVAL;
487
488 (void)realm;
489
490 *username = mem_ref(acc->auth_user);
491 *password = mem_ref(acc->auth_pass);
492
493 return 0;
494 }
495
496
account_aucodecl(const struct account * acc)497 struct list *account_aucodecl(const struct account *acc)
498 {
499 return (acc && !list_isempty(&acc->aucodecl))
500 ? (struct list *)&acc->aucodecl : baresip_aucodecl();
501 }
502
503
504 #ifdef USE_VIDEO
account_vidcodecl(const struct account * acc)505 struct list *account_vidcodecl(const struct account *acc)
506 {
507 return (acc && !list_isempty(&acc->vidcodecl))
508 ? (struct list *)&acc->vidcodecl : baresip_vidcodecl();
509 }
510 #endif
511
512
account_laddr(const struct account * acc)513 struct sip_addr *account_laddr(const struct account *acc)
514 {
515 return acc ? (struct sip_addr *)&acc->laddr : NULL;
516 }
517
518
account_regint(const struct account * acc)519 uint32_t account_regint(const struct account *acc)
520 {
521 return acc ? acc->regint : 0;
522 }
523
524
account_pubint(const struct account * acc)525 uint32_t account_pubint(const struct account *acc)
526 {
527 return acc ? acc->pubint : 0;
528 }
529
530
account_answermode(const struct account * acc)531 enum answermode account_answermode(const struct account *acc)
532 {
533 return acc ? acc->answermode : ANSWERMODE_MANUAL;
534 }
535
536
account_aor(const struct account * acc)537 const char *account_aor(const struct account *acc)
538 {
539 return acc ? acc->aor : NULL;
540 }
541
542
543 /**
544 * Get the authentication username of an account
545 *
546 * @param acc User-Agent account
547 *
548 * @return Authentication username
549 */
account_auth_user(const struct account * acc)550 const char *account_auth_user(const struct account *acc)
551 {
552 return acc ? acc->auth_user : NULL;
553 }
554
555
556 /**
557 * Get the SIP authentication password of an account
558 *
559 * @param acc User-Agent account
560 *
561 * @return Authentication password
562 */
account_auth_pass(const struct account * acc)563 const char *account_auth_pass(const struct account *acc)
564 {
565 return acc ? acc->auth_pass : NULL;
566 }
567
568
569 /**
570 * Get the outbound SIP server of an account
571 *
572 * @param acc User-Agent account
573 * @param ix Index starting at zero
574 *
575 * @return Outbound SIP proxy, NULL if not configured
576 */
account_outbound(const struct account * acc,unsigned ix)577 const char *account_outbound(const struct account *acc, unsigned ix)
578 {
579 if (!acc || ix >= ARRAY_SIZE(acc->outboundv))
580 return NULL;
581
582 return acc->outboundv[ix];
583 }
584
585
586 /**
587 * Get the audio packet-time (ptime) of an account
588 *
589 * @param acc User-Agent account
590 *
591 * @return Packet-time (ptime)
592 */
account_ptime(const struct account * acc)593 uint32_t account_ptime(const struct account *acc)
594 {
595 return acc ? acc->ptime : 0;
596 }
597
598
599 /**
600 * Get the STUN username of an account
601 *
602 * @param acc User-Agent account
603 *
604 * @return STUN username
605 */
account_stun_user(const struct account * acc)606 const char *account_stun_user(const struct account *acc)
607 {
608 return acc ? acc->stun_user : NULL;
609 }
610
611
612 /**
613 * Get the STUN password of an account
614 *
615 * @param acc User-Agent account
616 *
617 * @return STUN password
618 */
account_stun_pass(const struct account * acc)619 const char *account_stun_pass(const struct account *acc)
620 {
621 return acc ? acc->stun_pass : NULL;
622 }
623
624
625 /**
626 * Get the STUN hostname of an account
627 *
628 * @param acc User-Agent account
629 *
630 * @return STUN hostname
631 */
account_stun_host(const struct account * acc)632 const char *account_stun_host(const struct account *acc)
633 {
634 return acc ? acc->stun_host : NULL;
635 }
636
637
answermode_str(enum answermode mode)638 static const char *answermode_str(enum answermode mode)
639 {
640 switch (mode) {
641
642 case ANSWERMODE_MANUAL: return "manual";
643 case ANSWERMODE_EARLY: return "early";
644 case ANSWERMODE_AUTO: return "auto";
645 default: return "???";
646 }
647 }
648
649
account_debug(struct re_printf * pf,const struct account * acc)650 int account_debug(struct re_printf *pf, const struct account *acc)
651 {
652 struct le *le;
653 size_t i;
654 int err = 0;
655
656 if (!acc)
657 return 0;
658
659 err |= re_hprintf(pf, "\nAccount:\n");
660
661 err |= re_hprintf(pf, " address: %s\n", acc->buf);
662 err |= re_hprintf(pf, " luri: %H\n",
663 uri_encode, &acc->luri);
664 err |= re_hprintf(pf, " aor: %s\n", acc->aor);
665 err |= re_hprintf(pf, " dispname: %s\n", acc->dispname);
666 err |= re_hprintf(pf, " answermode: %s\n",
667 answermode_str(acc->answermode));
668 if (!list_isempty(&acc->aucodecl)) {
669 err |= re_hprintf(pf, " audio_codecs:");
670 for (le = list_head(&acc->aucodecl); le; le = le->next) {
671 const struct aucodec *ac = le->data;
672 err |= re_hprintf(pf, " %s/%u/%u",
673 ac->name, ac->srate, ac->ch);
674 }
675 err |= re_hprintf(pf, "\n");
676 }
677 err |= re_hprintf(pf, " auth_user: %s\n", acc->auth_user);
678 err |= re_hprintf(pf, " mediaenc: %s\n",
679 acc->mencid ? acc->mencid : "none");
680 err |= re_hprintf(pf, " medianat: %s\n",
681 acc->mnatid ? acc->mnatid : "none");
682 for (i=0; i<ARRAY_SIZE(acc->outboundv); i++) {
683 if (acc->outboundv[i]) {
684 err |= re_hprintf(pf, " outbound%d: %s\n",
685 i+1, acc->outboundv[i]);
686 }
687 }
688 err |= re_hprintf(pf, " ptime: %u\n", acc->ptime);
689 err |= re_hprintf(pf, " regint: %u\n", acc->regint);
690 err |= re_hprintf(pf, " pubint: %u\n", acc->pubint);
691 err |= re_hprintf(pf, " regq: %s\n", acc->regq);
692 err |= re_hprintf(pf, " rtpkeep: %s\n", acc->rtpkeep);
693 err |= re_hprintf(pf, " sipnat: %s\n", acc->sipnat);
694 err |= re_hprintf(pf, " stunserver: stun:%s@%s:%u\n",
695 acc->stun_user, acc->stun_host, acc->stun_port);
696 if (!list_isempty(&acc->vidcodecl)) {
697 err |= re_hprintf(pf, " video_codecs:");
698 for (le = list_head(&acc->vidcodecl); le; le = le->next) {
699 const struct vidcodec *vc = le->data;
700 err |= re_hprintf(pf, " %s", vc->name);
701 }
702 err |= re_hprintf(pf, "\n");
703 }
704
705 return err;
706 }
707