comparison svr-authpubkeyoptions.c @ 476:df7f7da7f6e4 pubkey-options

- Rework pubkey options to be more careful about buffer lengths. Needs review.
author Matt Johnston <matt@ucc.asn.au>
date Fri, 12 Sep 2008 17:23:56 +0000
parents 52a644e7b8e1
children 43bbe17d6ba0
comparison
equal deleted inserted replaced
475:52a644e7b8e1 476:df7f7da7f6e4
100 m_free(ses.authstate.pubkey_options); 100 m_free(ses.authstate.pubkey_options);
101 ses.authstate.pubkey_options = NULL; 101 ses.authstate.pubkey_options = NULL;
102 } 102 }
103 } 103 }
104 104
105 /* helper for svr_add_pubkey_options. returns DROPBEAR_SUCCESS if the option is matched,
106 and increments the options_buf */
107 static int match_option(buffer *options_buf, const char *opt_name) {
108 const int len = strlen(opt_name);
109 if (options_buf->len - options_buf->pos < len) {
110 return DROPBEAR_FAILURE;
111 }
112 if (strncasecmp(buf_getptr(options_buf, len), opt_name, len) == 0) {
113 buf_incrpos(options_buf, len);
114 return DROPBEAR_SUCCESS;
115 }
116 return DROPBEAR_FAILURE;
117 }
118
105 /* Parse pubkey options and set ses.authstate.pubkey_options accordingly. 119 /* Parse pubkey options and set ses.authstate.pubkey_options accordingly.
106 * Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */ 120 * Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */
107 int svr_add_pubkey_options(const char* opts) { 121 int svr_add_pubkey_options(buffer *options_buf, int line_num, const char* filename) {
108 const char *cp;
109 int i;
110 int ret = DROPBEAR_FAILURE; 122 int ret = DROPBEAR_FAILURE;
111 123
112 TRACE(("enter addpubkeyoptions")) 124 TRACE(("enter addpubkeyoptions"))
113 125
114 if (!opts || *opts == ' ') {
115 /* no option, success */
116 ret = DROPBEAR_SUCCESS;
117 goto end;
118 }
119
120 ses.authstate.pubkey_options = (struct PubKeyOptions*)m_malloc(sizeof( struct PubKeyOptions )); 126 ses.authstate.pubkey_options = (struct PubKeyOptions*)m_malloc(sizeof( struct PubKeyOptions ));
121 127 memset(ses.authstate.pubkey_options, '\0', sizeof(*ses.authstate.pubkey_options));
122 while (*opts && *opts != ' ' && *opts != '\t') { 128
123 cp = "no-port-forwarding"; 129 buf_setpos(options_buf, 0);
124 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 130 while (options_buf->pos < options_buf->len) {
131 if (match_option(options_buf, "no-port-forwarding") == DROPBEAR_SUCCESS) {
125 dropbear_log(LOG_WARNING, "Port forwarding disabled."); 132 dropbear_log(LOG_WARNING, "Port forwarding disabled.");
126 ses.authstate.pubkey_options->no_port_forwarding_flag = 1; 133 ses.authstate.pubkey_options->no_port_forwarding_flag = 1;
127 opts += strlen(cp);
128 goto next_option; 134 goto next_option;
129 } 135 }
130 #ifdef ENABLE_AGENTFWD 136 #ifdef ENABLE_AGENTFWD
131 cp = "no-agent-forwarding"; 137 if (match_option(options_buf, "no-agent-forwarding") == DROPBEAR_SUCCESS) {
132 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
133 dropbear_log(LOG_WARNING, "Agent forwarding disabled."); 138 dropbear_log(LOG_WARNING, "Agent forwarding disabled.");
134 ses.authstate.pubkey_options->no_agent_forwarding_flag = 1; 139 ses.authstate.pubkey_options->no_agent_forwarding_flag = 1;
135 opts += strlen(cp);
136 goto next_option; 140 goto next_option;
137 } 141 }
138 #endif 142 #endif
139 #ifdef ENABLE_X11FWD 143 #ifdef ENABLE_X11FWD
140 cp = "no-X11-forwarding"; 144 if (match_option(options_buf, "no-X11-forwarding") == DROPBEAR_SUCCESS) {
141 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
142 dropbear_log(LOG_WARNING, "X11 forwarding disabled."); 145 dropbear_log(LOG_WARNING, "X11 forwarding disabled.");
143 ses.authstate.pubkey_options->no_x11_forwarding_flag = 1; 146 ses.authstate.pubkey_options->no_x11_forwarding_flag = 1;
144 opts += strlen(cp);
145 goto next_option; 147 goto next_option;
146 } 148 }
147 #endif 149 #endif
148 cp = "no-pty"; 150 if (match_option(options_buf, "no-pty") == DROPBEAR_SUCCESS) {
149 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
150 dropbear_log(LOG_WARNING, "Pty allocation disabled."); 151 dropbear_log(LOG_WARNING, "Pty allocation disabled.");
151 ses.authstate.pubkey_options->no_pty_flag = 1; 152 ses.authstate.pubkey_options->no_pty_flag = 1;
152 opts += strlen(cp); 153 goto next_option;
153 goto next_option; 154 }
154 } 155 if (match_option(options_buf, "command=\"") == DROPBEAR_SUCCESS) {
155 cp = "command=\""; 156 int escaped = 0;
156 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 157 const unsigned char* command_start = buf_getptr(options_buf, 0);
157 opts += strlen(cp); 158 while (options_buf->pos < options_buf->len) {
158 ses.authstate.pubkey_options->forced_command = (char*)m_malloc(strlen(opts) + 1); 159 const char c = buf_getbyte(options_buf);
159 i = 0; 160 if (!escaped && c == '"') {
160 while (*opts) { 161 const int command_len = buf_getptr(options_buf, 0) - command_start;
161 if (*opts == '"') 162 ses.authstate.pubkey_options->forced_command = m_malloc(command_len);
162 break; 163 memcpy(ses.authstate.pubkey_options->forced_command,
163 if (*opts == '\\' && opts[1] == '"') { 164 command_start, command_len-1);
164 opts += 2; 165 ses.authstate.pubkey_options->forced_command[command_len-1] = '\0';
165 ses.authstate.pubkey_options->forced_command[i++] = '"'; 166 dropbear_log(LOG_WARNING, "Forced command '%s'",
166 continue; 167 ses.authstate.pubkey_options->forced_command);
168 goto next_option;
167 } 169 }
168 ses.authstate.pubkey_options->forced_command[i++] = *opts++; 170 escaped = (!escaped && c == '\\');
169 } 171 }
170 if (!*opts) { 172 dropbear_log(LOG_WARNING, "Badly formatted command= authorized_keys option");
171 dropbear_log(LOG_WARNING, 173 goto bad_option;
172 "Missing end quote in public key command option"); 174 }
173 m_free(ses.authstate.pubkey_options->forced_command); 175
174 ses.authstate.pubkey_options->forced_command = NULL; 176 next_option:
175 goto bad_option;
176 }
177 ses.authstate.pubkey_options->forced_command[i] = '\0';
178 if (strlen(ses.authstate.pubkey_options->forced_command) > MAX_CMD_LEN) {
179 dropbear_log(LOG_WARNING,
180 "Public key option command too long (>MAX_CMD_LEN).");
181 m_free(ses.authstate.pubkey_options->forced_command);
182 ses.authstate.pubkey_options->forced_command = NULL;
183 goto bad_option;
184 }
185 dropbear_log(LOG_WARNING, "Forced command '%s'",
186 ses.authstate.pubkey_options->forced_command);
187 opts++;
188 goto next_option;
189 }
190 next_option:
191 /* 177 /*
192 * Skip the comma, and move to the next option 178 * Skip the comma, and move to the next option
193 * (or break out if there are no more). 179 * (or break out if there are no more).
194 */ 180 */
195 if (!*opts) { 181 if (options_buf->pos < options_buf->len
196 TRACE(("Bugs in svr-chansession.c pubkey option processing.")) 182 && buf_getbyte(options_buf) != ',') {
197 }
198 if (*opts == ' ' || *opts == '\t') {
199 break; /* End of options. */
200 }
201 if (*opts != ',') {
202 goto bad_option; 183 goto bad_option;
203 } 184 }
204 opts++;
205 /* Process the next option. */ 185 /* Process the next option. */
206 } 186 }
207 /* parsed all options with no problem */ 187 /* parsed all options with no problem */
208 ret = DROPBEAR_SUCCESS; 188 ret = DROPBEAR_SUCCESS;
209 goto end; 189 goto end;
210 190
211 bad_option: 191 bad_option:
212 ret = DROPBEAR_FAILURE; 192 ret = DROPBEAR_FAILURE;
213 m_free(ses.authstate.pubkey_options); 193 m_free(ses.authstate.pubkey_options);
214 ses.authstate.pubkey_options = NULL; 194 ses.authstate.pubkey_options = NULL;
215 dropbear_log(LOG_WARNING, "Bad public key options : '%.50s'", opts); 195 dropbear_log(LOG_WARNING, "Bad public key options at %s:%d", filename, line_num);
216 196
217 end: 197 end:
218 TRACE(("leave addpubkeyoptions")) 198 TRACE(("leave addpubkeyoptions"))
219 return ret; 199 return ret;
220
221 } 200 }
222 201
223 #endif 202 #endif