Skip to content

Commit fb99ea6

Browse files
committed
app_predial: Improve robustness of user agent checks.
* Abort if the channel technology is NULL, which can happen if evaluating the function from the CLI. Previously, this resulted in NULL dereference. * Warn user if multiple PJSIP contacts are detected, since this will result in failure, and is probably an undesired scenario in and of itself. * Add additional debug and failure logging for PJSIP user agent evaluation.
1 parent 2377aa3 commit fb99ea6

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

apps/app_predial.c

+36-11
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ static int get_user_agent(struct ast_channel *chan, char *buf, size_t len, char
9696
char workspace[256];
9797
char device_name[256];
9898
char *endpoint;
99+
const char *tech;
100+
101+
if (!chan) {
102+
ast_log(LOG_ERROR, "Missing channel\n");
103+
return -1;
104+
}
99105

100106
if (!ast_strlen_zero(device)) { /* we were given a device to use */
101107
endpoint = strchr(device, '/');
@@ -119,28 +125,47 @@ static int get_user_agent(struct ast_channel *chan, char *buf, size_t len, char
119125

120126
endpoint++; /* Eat the slash so we just have the name without the tech */
121127

128+
if (!ast_channel_tech(chan)) { /* This could be NULL, like if evaluating a function from the CLI */
129+
ast_log(LOG_ERROR, "Channel has no tech?\n");
130+
return -1;
131+
}
132+
tech = ast_channel_tech(chan)->type;
122133
/* Can't use CHANNEL(useragent) in predial unfortunately... only works when channel is really there */
123-
if (!strcasecmp(ast_channel_tech(chan)->type, "PJSIP")) {
134+
if (!strcasecmp(tech, "PJSIP")) {
124135
snprintf(tmp, sizeof(tmp), "PJSIP_AOR(%s,contact)", endpoint);
125-
ast_func_read(chan, tmp, workspace, sizeof(workspace));
136+
if (ast_func_read(chan, tmp, workspace, sizeof(workspace))) {
137+
ast_log(LOG_ERROR, "Failed to get contact for %s\n", endpoint);
138+
return -1;
139+
}
126140
if (ast_strlen_zero(workspace)) {
127141
ast_log(LOG_WARNING, "No AOR found for %s\n", endpoint);
128142
return -1;
129143
}
144+
ast_debug(3, "Contact for endpoint %s is %s\n", endpoint, workspace);
145+
/* If multiple contacts are present, then there's no real way to know which one to use.
146+
* Just yell at the user that there should only be 1 contact! */
147+
if (strchr(workspace, ',')) {
148+
ast_log(LOG_WARNING, "Multiple contacts detected for endpoint '%s': %s\n", endpoint, workspace);
149+
/* This will probably fail now, but go ahead and fail anyways */
150+
}
130151
snprintf(tmp, sizeof(tmp), "PJSIP_CONTACT(%s,user_agent)", workspace);
131-
ast_func_read(chan, tmp, buf, len);
152+
if (ast_func_read(chan, tmp, buf, len)) {
153+
ast_log(LOG_ERROR, "Failed to get user agent using contact %s\n", workspace);
154+
return -1;
155+
}
132156
ast_debug(1, "User agent of PJSIP/%s is '%s'\n", endpoint, buf);
133-
return 0;
134-
} else if (!strcasecmp(ast_channel_tech(chan)->type, "SIP")) {
157+
} else if (!strcasecmp(tech, "SIP")) {
135158
snprintf(tmp, sizeof(tmp), "SIPPEER(%s,useragent)", endpoint);
136-
ast_func_read(chan, tmp, buf, len);
159+
if (ast_func_read(chan, tmp, buf, len)) {
160+
ast_log(LOG_ERROR, "Failed to get user agent for %s\n", endpoint);
161+
return -1;
162+
}
137163
ast_debug(1, "User agent of SIP/%s is '%s'\n", endpoint, buf);
138-
return 0;
164+
} else {
165+
ast_log(LOG_WARNING, "Unsupported channel technology: %s\n", ast_channel_tech(chan)->type);
166+
return -1;
139167
}
140-
141-
ast_log(LOG_WARNING, "Unsupported channel technology: %s\n", ast_channel_tech(chan)->type);
142-
143-
return -1;
168+
return 0;
144169
}
145170

146171
/*! \brief Somewhat arbitrary, but broken down by manufacturer / vendor / things that respond differently. */

0 commit comments

Comments
 (0)