diff options
| -rw-r--r-- | applets/applets.c | 130 |
1 files changed, 65 insertions, 65 deletions
diff --git a/applets/applets.c b/applets/applets.c index a6e6598cc..8171a309d 100644 --- a/applets/applets.c +++ b/applets/applets.c | |||
| @@ -59,22 +59,22 @@ static int config_ok; | |||
| 59 | 59 | ||
| 60 | #define CONFIG_FILE "/etc/busybox.conf" | 60 | #define CONFIG_FILE "/etc/busybox.conf" |
| 61 | 61 | ||
| 62 | // applets [] is const, so we have to define this "override" structure | 62 | /* applets [] is const, so we have to define this "override" structure */ |
| 63 | struct BB_suid_config { | 63 | struct BB_suid_config { |
| 64 | struct BB_applet *m_applet; | 64 | struct BB_applet *m_applet; |
| 65 | 65 | ||
| 66 | uid_t m_uid; | 66 | uid_t m_uid; |
| 67 | gid_t m_gid; | 67 | gid_t m_gid; |
| 68 | mode_t m_mode; | 68 | mode_t m_mode; |
| 69 | 69 | ||
| 70 | struct BB_suid_config *m_next; | 70 | struct BB_suid_config *m_next; |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | static struct BB_suid_config *suid_config; | 73 | static struct BB_suid_config *suid_config; |
| 74 | 74 | ||
| 75 | #endif // CONFIG_FEATURE_SUID_CONFIG | 75 | #endif /* CONFIG_FEATURE_SUID_CONFIG */ |
| 76 | 76 | ||
| 77 | #endif // CONFIG_FEATURE_SUID | 77 | #endif /* CONFIG_FEATURE_SUID */ |
| 78 | 78 | ||
| 79 | 79 | ||
| 80 | 80 | ||
| @@ -142,7 +142,7 @@ void run_applet_by_name(const char *name, int argc, char **argv) | |||
| 142 | #ifdef CONFIG_FEATURE_SUID | 142 | #ifdef CONFIG_FEATURE_SUID |
| 143 | check_suid ( applet_using ); | 143 | check_suid ( applet_using ); |
| 144 | #endif | 144 | #endif |
| 145 | 145 | ||
| 146 | exit((*(applet_using->main)) (argc, argv)); | 146 | exit((*(applet_using->main)) (argc, argv)); |
| 147 | } | 147 | } |
| 148 | /* Just in case they have renamed busybox - Check argv[1] */ | 148 | /* Just in case they have renamed busybox - Check argv[1] */ |
| @@ -157,17 +157,17 @@ void run_applet_by_name(const char *name, int argc, char **argv) | |||
| 157 | 157 | ||
| 158 | #ifdef CONFIG_FEATURE_SUID_CONFIG | 158 | #ifdef CONFIG_FEATURE_SUID_CONFIG |
| 159 | 159 | ||
| 160 | // check if u is member of group g | 160 | /* check if u is member of group g */ |
| 161 | static int ingroup ( uid_t u, gid_t g ) | 161 | static int ingroup ( uid_t u, gid_t g ) |
| 162 | { | 162 | { |
| 163 | struct group *grp = getgrgid ( g ); | 163 | struct group *grp = getgrgid ( g ); |
| 164 | 164 | ||
| 165 | if ( grp ) { | 165 | if ( grp ) { |
| 166 | char **mem; | 166 | char **mem; |
| 167 | 167 | ||
| 168 | for ( mem = grp-> gr_mem; *mem; mem++ ) { | 168 | for ( mem = grp-> gr_mem; *mem; mem++ ) { |
| 169 | struct passwd *pwd = getpwnam ( *mem ); | 169 | struct passwd *pwd = getpwnam ( *mem ); |
| 170 | 170 | ||
| 171 | if ( pwd && ( pwd-> pw_uid == u )) | 171 | if ( pwd && ( pwd-> pw_uid == u )) |
| 172 | return 1; | 172 | return 1; |
| 173 | } | 173 | } |
| @@ -180,43 +180,43 @@ static int ingroup ( uid_t u, gid_t g ) | |||
| 180 | 180 | ||
| 181 | void check_suid ( struct BB_applet *applet ) | 181 | void check_suid ( struct BB_applet *applet ) |
| 182 | { | 182 | { |
| 183 | uid_t ruid = getuid ( ); // real [ug]id | 183 | uid_t ruid = getuid ( ); /* real [ug]id */ |
| 184 | uid_t rgid = getgid ( ); | 184 | uid_t rgid = getgid ( ); |
| 185 | 185 | ||
| 186 | #ifdef CONFIG_FEATURE_SUID_CONFIG | 186 | #ifdef CONFIG_FEATURE_SUID_CONFIG |
| 187 | if ( config_ok ) { | 187 | if ( config_ok ) { |
| 188 | struct BB_suid_config *sct; | 188 | struct BB_suid_config *sct; |
| 189 | 189 | ||
| 190 | for ( sct = suid_config; sct; sct = sct-> m_next ) { | 190 | for ( sct = suid_config; sct; sct = sct-> m_next ) { |
| 191 | if ( sct-> m_applet == applet ) | 191 | if ( sct-> m_applet == applet ) |
| 192 | break; | 192 | break; |
| 193 | } | 193 | } |
| 194 | if ( sct ) { | 194 | if ( sct ) { |
| 195 | mode_t m = sct-> m_mode; | 195 | mode_t m = sct-> m_mode; |
| 196 | 196 | ||
| 197 | if ( sct-> m_uid == ruid ) // same uid | 197 | if ( sct-> m_uid == ruid ) /* same uid */ |
| 198 | m >>= 6; | 198 | m >>= 6; |
| 199 | else if (( sct-> m_gid == rgid ) || ingroup ( ruid, sct-> m_gid )) // same group / in group | 199 | else if (( sct-> m_gid == rgid ) || ingroup ( ruid, sct-> m_gid )) /* same group / in group */ |
| 200 | m >>= 3; | 200 | m >>= 3; |
| 201 | 201 | ||
| 202 | if (!( m & S_IXOTH )) // is x bit not set ? | 202 | if (!( m & S_IXOTH )) /* is x bit not set ? */ |
| 203 | error_msg_and_die ( "You have no permission to run this applet!" ); | 203 | error_msg_and_die ( "You have no permission to run this applet!" ); |
| 204 | 204 | ||
| 205 | if (( sct-> m_mode & ( S_ISGID | S_IXGRP )) == ( S_ISGID | S_IXGRP )) { // *both* have to be set for sgid | 205 | if (( sct-> m_mode & ( S_ISGID | S_IXGRP )) == ( S_ISGID | S_IXGRP )) { /* *both* have to be set for sgid */ |
| 206 | if ( setegid ( sct-> m_gid )) | 206 | if ( setegid ( sct-> m_gid )) |
| 207 | error_msg_and_die ( "BusyBox binary has insufficient rights to set proper GID for applet!" ); | 207 | error_msg_and_die ( "BusyBox binary has insufficient rights to set proper GID for applet!" ); |
| 208 | } | 208 | } |
| 209 | else | 209 | else |
| 210 | setgid ( rgid ); // no sgid -> drop | 210 | setgid ( rgid ); /* no sgid -> drop */ |
| 211 | 211 | ||
| 212 | if ( sct-> m_mode & S_ISUID ) { | 212 | if ( sct-> m_mode & S_ISUID ) { |
| 213 | if ( seteuid ( sct-> m_uid )) | 213 | if ( seteuid ( sct-> m_uid )) |
| 214 | error_msg_and_die ( "BusyBox binary has insufficient rights to set proper UID for applet!" ); | 214 | error_msg_and_die ( "BusyBox binary has insufficient rights to set proper UID for applet!" ); |
| 215 | } | 215 | } |
| 216 | else | 216 | else |
| 217 | setuid ( ruid ); // no suid -> drop | 217 | setuid ( ruid ); /* no suid -> drop */ |
| 218 | } | 218 | } |
| 219 | else { // default: drop all priviledges | 219 | else { /* default: drop all priviledges */ |
| 220 | setgid ( rgid ); | 220 | setgid ( rgid ); |
| 221 | setuid ( ruid ); | 221 | setuid ( ruid ); |
| 222 | } | 222 | } |
| @@ -225,7 +225,7 @@ void check_suid ( struct BB_applet *applet ) | |||
| 225 | else { | 225 | else { |
| 226 | #ifndef CONFIG_FEATURE_SUID_CONFIG_QUIET | 226 | #ifndef CONFIG_FEATURE_SUID_CONFIG_QUIET |
| 227 | static int onetime = 0; | 227 | static int onetime = 0; |
| 228 | 228 | ||
| 229 | if ( !onetime ) { | 229 | if ( !onetime ) { |
| 230 | onetime = 1; | 230 | onetime = 1; |
| 231 | fprintf ( stderr, "Using fallback suid method\n" ); | 231 | fprintf ( stderr, "Using fallback suid method\n" ); |
| @@ -239,7 +239,7 @@ void check_suid ( struct BB_applet *applet ) | |||
| 239 | error_msg_and_die ( "This applet requires root priviledges!" ); | 239 | error_msg_and_die ( "This applet requires root priviledges!" ); |
| 240 | } | 240 | } |
| 241 | else if ( applet-> need_suid == _BB_SUID_NEVER ) { | 241 | else if ( applet-> need_suid == _BB_SUID_NEVER ) { |
| 242 | setgid ( rgid ); // drop all priviledges | 242 | setgid ( rgid ); /* drop all priviledges */ |
| 243 | setuid ( ruid ); | 243 | setuid ( ruid ); |
| 244 | } | 244 | } |
| 245 | } | 245 | } |
| @@ -258,90 +258,90 @@ int parse_config_file ( void ) | |||
| 258 | int lc = 0; | 258 | int lc = 0; |
| 259 | 259 | ||
| 260 | suid_config = 0; | 260 | suid_config = 0; |
| 261 | 261 | ||
| 262 | // is there a config file ? | 262 | /* is there a config file ? */ |
| 263 | if ( stat ( CONFIG_FILE, &st ) == 0 ) { | 263 | if ( stat ( CONFIG_FILE, &st ) == 0 ) { |
| 264 | // is it owned by root with no write perm. for group and others ? | 264 | /* is it owned by root with no write perm. for group and others ? */ |
| 265 | if ( S_ISREG( st. st_mode ) && ( st. st_uid == 0 ) && (!( st. st_mode & ( S_IWGRP | S_IWOTH )))) { | 265 | if ( S_ISREG( st. st_mode ) && ( st. st_uid == 0 ) && (!( st. st_mode & ( S_IWGRP | S_IWOTH )))) { |
| 266 | // that's ok .. then try to open it | 266 | /* that's ok .. then try to open it */ |
| 267 | f = fopen ( CONFIG_FILE, "r" ); | 267 | f = fopen ( CONFIG_FILE, "r" ); |
| 268 | 268 | ||
| 269 | if ( f ) { | 269 | if ( f ) { |
| 270 | char buffer [256]; | 270 | char buffer [256]; |
| 271 | int section = 0; | 271 | int section = 0; |
| 272 | 272 | ||
| 273 | while ( fgets ( buffer, sizeof( buffer ) - 1, f )) { | 273 | while ( fgets ( buffer, sizeof( buffer ) - 1, f )) { |
| 274 | char c = buffer [0]; | 274 | char c = buffer [0]; |
| 275 | char *p; | 275 | char *p; |
| 276 | 276 | ||
| 277 | lc++; | 277 | lc++; |
| 278 | 278 | ||
| 279 | p = strchr ( buffer, '#' ); | 279 | p = strchr ( buffer, '#' ); |
| 280 | if ( p ) | 280 | if ( p ) |
| 281 | *p = 0; | 281 | *p = 0; |
| 282 | p = buffer + xstrlen ( buffer ); | 282 | p = buffer + xstrlen ( buffer ); |
| 283 | while (( p > buffer ) && isspace ( *--p )) | 283 | while (( p > buffer ) && isspace ( *--p )) |
| 284 | *p = 0; | 284 | *p = 0; |
| 285 | 285 | ||
| 286 | if ( p == buffer ) | 286 | if ( p == buffer ) |
| 287 | continue; | 287 | continue; |
| 288 | 288 | ||
| 289 | if ( c == '[' ) { | 289 | if ( c == '[' ) { |
| 290 | p = strchr ( buffer, ']' ); | 290 | p = strchr ( buffer, ']' ); |
| 291 | 291 | ||
| 292 | if ( !p || ( p == ( buffer + 1 ))) // no matching ] or empty [] | 292 | if ( !p || ( p == ( buffer + 1 ))) /* no matching ] or empty [] */ |
| 293 | parse_error ( "malformed section header" ); | 293 | parse_error ( "malformed section header" ); |
| 294 | 294 | ||
| 295 | *p = 0; | 295 | *p = 0; |
| 296 | 296 | ||
| 297 | if ( strcasecmp ( buffer + 1, "SUID" ) == 0 ) | 297 | if ( strcasecmp ( buffer + 1, "SUID" ) == 0 ) |
| 298 | section = 1; | 298 | section = 1; |
| 299 | else | 299 | else |
| 300 | section = -1; // unknown section - just skip | 300 | section = -1; /* unknown section - just skip */ |
| 301 | } | 301 | } |
| 302 | else if ( section ) { | 302 | else if ( section ) { |
| 303 | switch ( section ) { | 303 | switch ( section ) { |
| 304 | case 1: { // SUID | 304 | case 1: { /* SUID */ |
| 305 | int l; | 305 | int l; |
| 306 | struct BB_applet *applet; | 306 | struct BB_applet *applet; |
| 307 | 307 | ||
| 308 | p = strchr ( buffer, '=' ); // <key>[::space::]*=[::space::]*<value> | 308 | p = strchr ( buffer, '=' ); /* <key>[::space::]*=[::space::]*<value> */ |
| 309 | 309 | ||
| 310 | if ( !p || ( p == ( buffer + 1 ))) // no = or key is empty | 310 | if ( !p || ( p == ( buffer + 1 ))) /* no = or key is empty */ |
| 311 | parse_error ( "malformed keyword" ); | 311 | parse_error ( "malformed keyword" ); |
| 312 | 312 | ||
| 313 | l = p - buffer; | 313 | l = p - buffer; |
| 314 | while ( isspace ( buffer [--l] )) { } // skip whitespace | 314 | while ( isspace ( buffer [--l] )) { } /* skip whitespace */ |
| 315 | 315 | ||
| 316 | buffer [l+1] = 0; | 316 | buffer [l+1] = 0; |
| 317 | 317 | ||
| 318 | if (( applet = find_applet_by_name ( buffer ))) { | 318 | if (( applet = find_applet_by_name ( buffer ))) { |
| 319 | struct BB_suid_config *sct = xmalloc ( sizeof( struct BB_suid_config )); | 319 | struct BB_suid_config *sct = xmalloc ( sizeof( struct BB_suid_config )); |
| 320 | 320 | ||
| 321 | sct-> m_applet = applet; | 321 | sct-> m_applet = applet; |
| 322 | sct-> m_next = suid_config; | 322 | sct-> m_next = suid_config; |
| 323 | suid_config = sct; | 323 | suid_config = sct; |
| 324 | 324 | ||
| 325 | while ( isspace ( *++p )) { } // skip whitespace | 325 | while ( isspace ( *++p )) { } /* skip whitespace */ |
| 326 | 326 | ||
| 327 | sct-> m_mode = 0; | 327 | sct-> m_mode = 0; |
| 328 | 328 | ||
| 329 | switch ( *p++ ) { | 329 | switch ( *p++ ) { |
| 330 | case 'S': sct-> m_mode |= S_ISUID; break; | 330 | case 'S': sct-> m_mode |= S_ISUID; break; |
| 331 | case 's': sct-> m_mode |= S_ISUID; // no break | 331 | case 's': sct-> m_mode |= S_ISUID; /* no break */ |
| 332 | case 'x': sct-> m_mode |= S_IXUSR; break; | 332 | case 'x': sct-> m_mode |= S_IXUSR; break; |
| 333 | case '-': break; | 333 | case '-': break; |
| 334 | default : parse_error ( "invalid user mode" ); | 334 | default : parse_error ( "invalid user mode" ); |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | switch ( *p++ ) { | 337 | switch ( *p++ ) { |
| 338 | case 's': sct-> m_mode |= S_ISGID; // no break | 338 | case 's': sct-> m_mode |= S_ISGID; /* no break */ |
| 339 | case 'x': sct-> m_mode |= S_IXGRP; break; | 339 | case 'x': sct-> m_mode |= S_IXGRP; break; |
| 340 | case 'S': break; | 340 | case 'S': break; |
| 341 | case '-': break; | 341 | case '-': break; |
| 342 | default : parse_error ( "invalid group mode" ); | 342 | default : parse_error ( "invalid group mode" ); |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | switch ( *p ) { | 345 | switch ( *p ) { |
| 346 | case 't': | 346 | case 't': |
| 347 | case 'x': sct-> m_mode |= S_IXOTH; break; | 347 | case 'x': sct-> m_mode |= S_IXOTH; break; |
| @@ -349,9 +349,9 @@ int parse_config_file ( void ) | |||
| 349 | case '-': break; | 349 | case '-': break; |
| 350 | default : parse_error ( "invalid other mode" ); | 350 | default : parse_error ( "invalid other mode" ); |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | while ( isspace ( *++p )) { } // skip whitespace | 353 | while ( isspace ( *++p )) { } /* skip whitespace */ |
| 354 | 354 | ||
| 355 | if ( isdigit ( *p )) { | 355 | if ( isdigit ( *p )) { |
| 356 | sct-> m_uid = strtol ( p, &p, 10 ); | 356 | sct-> m_uid = strtol ( p, &p, 10 ); |
| 357 | if ( *p++ != '.' ) | 357 | if ( *p++ != '.' ) |
| @@ -363,13 +363,13 @@ int parse_config_file ( void ) | |||
| 363 | 363 | ||
| 364 | if ( !p2 ) | 364 | if ( !p2 ) |
| 365 | parse_error ( "parsing <uid>.<gid>" ); | 365 | parse_error ( "parsing <uid>.<gid>" ); |
| 366 | 366 | ||
| 367 | *p2 = 0; | 367 | *p2 = 0; |
| 368 | pwd = getpwnam ( p ); | 368 | pwd = getpwnam ( p ); |
| 369 | 369 | ||
| 370 | if ( !pwd ) | 370 | if ( !pwd ) |
| 371 | parse_error ( "invalid user name" ); | 371 | parse_error ( "invalid user name" ); |
| 372 | 372 | ||
| 373 | sct-> m_uid = pwd-> pw_uid; | 373 | sct-> m_uid = pwd-> pw_uid; |
| 374 | p = p2 + 1; | 374 | p = p2 + 1; |
| 375 | } | 375 | } |
| @@ -377,16 +377,16 @@ int parse_config_file ( void ) | |||
| 377 | sct-> m_gid = strtol ( p, &p, 10 ); | 377 | sct-> m_gid = strtol ( p, &p, 10 ); |
| 378 | else { | 378 | else { |
| 379 | struct group *grp = getgrnam ( p ); | 379 | struct group *grp = getgrnam ( p ); |
| 380 | 380 | ||
| 381 | if ( !grp ) | 381 | if ( !grp ) |
| 382 | parse_error ( "invalid group name" ); | 382 | parse_error ( "invalid group name" ); |
| 383 | 383 | ||
| 384 | sct-> m_gid = grp-> gr_gid; | 384 | sct-> m_gid = grp-> gr_gid; |
| 385 | } | 385 | } |
| 386 | } | 386 | } |
| 387 | break; | 387 | break; |
| 388 | } | 388 | } |
| 389 | default: // unknown - skip | 389 | default: /* unknown - skip */ |
| 390 | break; | 390 | break; |
| 391 | } | 391 | } |
| 392 | } | 392 | } |
| @@ -398,8 +398,8 @@ int parse_config_file ( void ) | |||
| 398 | } | 398 | } |
| 399 | } | 399 | } |
| 400 | } | 400 | } |
| 401 | return 0; // no config file or not readable (not an error) | 401 | return 0; /* no config file or not readable (not an error) */ |
| 402 | 402 | ||
| 403 | pe_label: | 403 | pe_label: |
| 404 | fprintf ( stderr, "Parse error in %s, line %d: %s\n", CONFIG_FILE, lc, err ); | 404 | fprintf ( stderr, "Parse error in %s, line %d: %s\n", CONFIG_FILE, lc, err ); |
| 405 | 405 | ||
