~ubuntu-branches/ubuntu/precise/boinc/precise

« back to all changes in this revision

Viewing changes to client/check_security.cpp

Tags: 6.12.8+dfsg-1
* New upstream release.
* Simplified debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include "error_numbers.h"
36
36
#include "file_names.h"
37
37
 
38
 
static int CheckNestedDirectories(char * basepath, int depth, int use_sandbox);
 
38
#ifdef __WXMAC__                            // If Mac BOINC Manager
 
39
bool IsUserInGroupBM();
 
40
#endif
 
41
 
 
42
static int CheckNestedDirectories(char * basepath, int depth, int use_sandbox, int isManager);
39
43
 
40
44
#if (! defined(__WXMAC__) && ! defined(_MAC_INSTALLER))
41
45
static char * PersistentFGets(char *buf, size_t buflen, FILE *f);
45
49
#define REAL_BOINC_MASTER_NAME "boinc_master"
46
50
#define REAL_BOINC_PROJECT_NAME "boinc_project"
47
51
 
 
52
 
48
53
static char         boinc_master_user_name[64];
49
54
static char         boinc_master_group_name[64];
50
55
static char         boinc_project_user_name[64];
79
84
    ProcessSerialNumber ourPSN;
80
85
    ProcessInfoRec      pInfo;
81
86
    FSRef               ourFSRef;
82
 
    char                *p;
83
 
#endif
84
 
#ifdef _MAC_INSTALLER
85
 
    char                *p;
86
 
#endif
 
87
#endif
 
88
 
 
89
#define NUMBRANDS 3
 
90
 
 
91
char *saverName[NUMBRANDS];
 
92
 
 
93
saverName[0] = "BOINCSaver";
 
94
saverName[1] = "GridRepublic";
 
95
saverName[2] = "Progress Thru Processors";
87
96
 
88
97
    useFakeProjectUserAndGroup = ! use_sandbox;
89
98
#ifdef _DEBUG
91
100
        useFakeProjectUserAndGroup = 1;
92
101
#endif
93
102
#ifdef __APPLE__
94
 
    err = Gestalt(gestaltSystemVersion, &response);
 
103
    err = Gestalt(gestaltSystemVersion, (SInt32*)&response);
95
104
    if ((err == noErr) && (response < 0x1040))
96
105
        useFakeProjectUserAndGroup = 1;
97
106
#endif      // __APPLE__
149
158
 
150
159
        boinc_master_uid = sbuf.st_uid;
151
160
        boinc_master_gid = sbuf.st_gid;
 
161
 
 
162
#ifdef __WXMAC__
 
163
    if (!IsUserInGroupBM())
 
164
        return -1099;
 
165
#endif
152
166
    } else {
153
167
        boinc_master_uid = geteuid();
154
168
        boinc_master_gid = getegid();
155
 
 
156
169
    }
157
170
 
158
171
#ifdef _MAC_INSTALLER
203
216
        boinc_project_gid = grp->gr_gid;
204
217
    }
205
218
 
 
219
#if 0   // Manager is no longer setgid
206
220
#if (defined(__WXMAC__) || defined(_MAC_INSTALLER)) // If Mac BOINC Manager or installer
207
221
        // Get the full path to BOINC Manager executable inside this application's bundle
208
222
        strlcpy(full_path, dir_path, sizeof(full_path));
228
242
                return -1015;
229
243
        }
230
244
#endif
 
245
#endif   // Manager is no longer setgid
 
246
 
231
247
 
232
248
#ifdef _MAC_INSTALLER
233
249
        // Require absolute owner and group boinc_master:boinc_master
254
270
        // to avoid this risk.
255
271
 
256
272
        if (use_sandbox) {
257
 
            // Does gfx_switcher exist in screensaver bundle?
258
 
            strcpy(full_path, "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher");
259
 
            retval = stat(full_path, &sbuf);
260
 
            if (! retval) {
 
273
            for (int i=0; i<NUMBRANDS; i++) {
 
274
                // Does gfx_switcher exist in screensaver bundle?
 
275
                sprintf(full_path, "/Library/Screen Savers/%s.saver/Contents/Resources/gfx_switcher", saverName[i]);
 
276
                retval = stat(full_path, &sbuf);
 
277
                if (! retval) {
261
278
#ifdef _DEBUG
262
 
                if (sbuf.st_uid != boinc_master_uid)
263
 
                    return -1101;
264
 
 
265
 
                if (sbuf.st_gid != boinc_master_gid)
266
 
                    return -1102;
267
 
 
268
 
                if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != 0)
269
 
                    return -1103;
 
279
                    if (sbuf.st_uid != boinc_master_uid)
 
280
                        return -1101;
 
281
 
 
282
                    if (sbuf.st_gid != boinc_master_gid)
 
283
                        return -1102;
 
284
 
 
285
                    if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != 0)
 
286
                        return -1103;
270
287
#else
271
 
                if (sbuf.st_uid != 0)
272
 
                    return -1101;
273
 
 
274
 
                if (sbuf.st_gid != boinc_master_gid)
275
 
                    return -1102;
276
 
 
277
 
                if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != S_ISUID)
278
 
                    return -1103;
 
288
                    if (sbuf.st_uid != 0)
 
289
                        return -1101;
 
290
 
 
291
                    if (sbuf.st_gid != boinc_master_gid)
 
292
                        return -1102;
 
293
 
 
294
                    if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != S_ISUID)
 
295
                        return -1103;
279
296
#endif
 
297
                }
280
298
            }
281
299
        }
282
300
#endif
292
310
#else       // _MAC_INSTALLER
293
311
    getcwd(dir_path, sizeof(dir_path));             // Client or Manager
294
312
 
 
313
    if (! isManager) {                                   // If BOINC Client
295
314
    if (egid != boinc_master_gid)
296
 
        return -1019;     // Client or Manager should be running setgid boinc_master
 
315
            return -1019;     // Client should be running setgid boinc_master
297
316
 
298
 
    if (! isManager)                                    // If BOINC Client
299
317
        if (euid != boinc_master_uid)
300
318
            return -1020;     // BOINC Client should be running setuid boinc_master
 
319
    }
301
320
#endif
302
321
 
303
322
    retval = stat(dir_path, &sbuf);
328
347
    retval = stat(full_path, &sbuf);
329
348
    if (! retval) {                 // Client can create projects directory if it does not yet exist.  
330
349
        if (use_sandbox) {
331
 
            if (sbuf.st_gid != boinc_master_gid)
 
350
            if (sbuf.st_gid != boinc_project_gid)
332
351
                return -1024;
333
352
 
334
 
        if ((sbuf.st_mode & 0777) != 0775)
 
353
        if ((sbuf.st_mode & 0777) != 0770)
335
354
            return -1025;
336
355
        }
337
356
        
339
358
            return -1026;
340
359
 
341
360
        // Step through project directories
342
 
        retval = CheckNestedDirectories(full_path, 1, use_sandbox);
 
361
        retval = CheckNestedDirectories(full_path, 1, use_sandbox, isManager);
343
362
        if (retval)
344
363
            return retval;
345
364
    }
346
365
 
347
 
    strlcpy(full_path, dir_path, sizeof(dir_path));
 
366
    strlcpy(full_path, dir_path, sizeof(full_path));
348
367
    strlcat(full_path, "/", sizeof(full_path));
349
368
    strlcat(full_path, SLOTS_DIR, sizeof(full_path));
350
369
    retval = stat(full_path, &sbuf);
351
370
    if (! retval) {                 // Client can create slots directory if it does not yet exist.  
352
371
       if (use_sandbox) {
353
 
            if (sbuf.st_gid != boinc_master_gid)
 
372
            if (sbuf.st_gid != boinc_project_gid)
354
373
                return -1027;
355
374
 
356
 
            if ((sbuf.st_mode & 0777) != 0775)
 
375
            if ((sbuf.st_mode & 0777) != 0770)
357
376
                return -1028;
358
377
        }
359
378
        
361
380
            return -1029;
362
381
 
363
382
        // Step through slot directories
364
 
        retval = CheckNestedDirectories(full_path, 1, use_sandbox);
 
383
        retval = CheckNestedDirectories(full_path, 1, use_sandbox, isManager);
365
384
        if (retval)
366
385
            return retval;
367
386
    }
387
406
    }
388
407
 
389
408
    if (use_sandbox) {
390
 
        strlcpy(full_path, dir_path, sizeof(dir_path));
 
409
        strlcpy(full_path, dir_path, sizeof(full_path));
391
410
        strlcat(full_path, "/", sizeof(full_path));
392
411
        strlcat(full_path, SWITCHER_DIR, sizeof(full_path));
393
412
        retval = stat(full_path, &sbuf);
418
437
        if ((sbuf.st_mode & 07777) != 04050)
419
438
            return -1040;
420
439
 
421
 
        strlcpy(full_path, dir_path, sizeof(dir_path));
 
440
        strlcpy(full_path, dir_path, sizeof(full_path));
422
441
        strlcat(full_path, "/", sizeof(full_path));
423
442
        strlcat(full_path, SWITCHER_DIR, sizeof(full_path));
424
443
 
437
456
        if ((sbuf.st_mode & 07777) != 02500)
438
457
            return -1044;
439
458
 
440
 
        strlcpy(full_path, dir_path, sizeof(dir_path));
441
 
        strlcat(full_path, "/", sizeof(full_path));
442
 
        strlcat(full_path, SWITCHER_DIR, sizeof(full_path));
443
 
 
444
459
#ifdef __APPLE__
445
460
#if 0       // AppStats is deprecated as of version 5.8.15
446
461
        strlcat(full_path, "/", sizeof(full_path));
459
474
            return -1048;
460
475
#endif
461
476
#endif  // __APPLE__
 
477
 
 
478
        strlcpy(full_path, dir_path, sizeof(full_path));
 
479
        strlcat(full_path, "/", sizeof(full_path));
 
480
        strlcat(full_path, SS_CONFIG_FILE, sizeof(full_path));
 
481
 
 
482
        retval = stat(full_path, &sbuf);
 
483
        if (!retval) {
 
484
            if (sbuf.st_uid != boinc_master_uid)
 
485
                return -1051;
 
486
 
 
487
            if (sbuf.st_gid != boinc_master_gid)
 
488
                return -1052;
 
489
 
 
490
            if ((sbuf.st_mode & 0777) != 0664)
 
491
                return -1053;
 
492
        }   // Screensaver config file ss_config.xml exists
 
493
        
462
494
    }       // if (use_sandbox)
463
495
    
464
496
    return 0;
465
497
}
466
498
 
467
499
 
468
 
static int CheckNestedDirectories(char * basepath, int depth, int use_sandbox) {
 
500
static int CheckNestedDirectories(char * basepath, int depth, int use_sandbox, int isManager) {
469
501
    int             isDirectory;
470
502
    char            full_path[MAXPATHLEN];
471
503
    struct stat     sbuf;
472
504
    int             retval = 0;
473
505
    DIR             *dirp;
474
506
    dirent          *dp;
 
507
    static int      errShown = 0;
475
508
 
476
509
    dirp = opendir(basepath);
477
510
    if (dirp == NULL)           // Should never happen
546
579
        }           // if (!S_ISLNK(sbuf.st_mode))
547
580
        
548
581
        if (isDirectory && !S_ISLNK(sbuf.st_mode)) {
549
 
            if (use_sandbox && (depth > 1))
550
 
                if ((sbuf.st_uid != boinc_master_uid) && (sbuf.st_gid != boinc_master_gid))
551
 
                    continue;       // We can't check subdirectories owned by boinc_project
552
 
            
553
 
            retval = CheckNestedDirectories(full_path, depth + 1, use_sandbox);
 
582
            if (use_sandbox && (depth > 1)) {
 
583
                if ((! isManager) && (sbuf.st_uid != boinc_master_uid))
 
584
                    continue;       // Client can't check subdirectories owned by boinc_project
 
585
            }
 
586
            retval = CheckNestedDirectories(full_path, depth + 1, use_sandbox, isManager);
554
587
            if (retval)
555
588
                break;
556
589
        }
559
592
 
560
593
    closedir(dirp);
561
594
    
 
595
    if (retval && !errShown) {
 
596
        fprintf(stderr, "Permissions error %d at %s\n", retval, full_path);
 
597
        errShown = 1;
 
598
    }
562
599
    return retval;
563
600
}
564
601
 
620
657
        *q = '\0';
621
658
}
622
659
#endif
 
660
 
 
661
 
 
662
#ifdef __WXMAC__                            // If Mac BOINC Manager
 
663
bool IsUserInGroupBM() {
 
664
    group               *grp;
 
665
    gid_t               rgid;
 
666
    char                *userName, *groupMember;
 
667
    int                 i;
 
668
 
 
669
    grp = getgrnam(REAL_BOINC_MASTER_NAME);
 
670
    if (grp) {
 
671
        rgid = getgid();
 
672
        if (rgid == grp->gr_gid) {
 
673
            return true;                // User's primary group is boinc_master
 
674
        }
 
675
 
 
676
        // On some systems with Automatic Login set, getlogin() returns "root" for a 
 
677
        // time after the system is first booted, so we check "USER" environment variable.
 
678
        userName = getenv("USER");
 
679
        if (userName) {
 
680
            for (i=0; ; i++) {          // Step through all users in group boinc_master
 
681
                groupMember = grp->gr_mem[i];
 
682
                if (groupMember == NULL)
 
683
                    return false;       // User is not a member of group boinc_master
 
684
                if (strcmp(userName, groupMember) == 0) {
 
685
                    return true;        // User is a member of group boinc_master
 
686
                }
 
687
            }       // for (i)
 
688
        }           // if (userName)
 
689
    }               // if grp
 
690
 
 
691
    return false;
 
692
}
 
693
#endif  // __WXMAC__