~ubuntu-branches/ubuntu/karmic/likewise-open/karmic

« back to all changes in this revision

Viewing changes to samba/source/nsswitch/winbind_nss_aix.c

  • Committer: Bazaar Package Importer
  • Author(s): Rick Clark
  • Date: 2008-08-27 08:56:20 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080827085620-5q0f58b9qtog9myq
Tags: 4.1.0.2956-0ubuntu1
* missing-likewise-logo.diff: removed
* fixed copyright notice
* updated Standards-Version to 3.8.0
* removed path from command in prerm
* removed stop in S runlevel

Show diffs side-by-side

added added

removed removed

Lines of Context:
115
115
 
116
116
static void *list_realloc(struct mem_list**list, void* p, size_t size)
117
117
{
118
 
        struct mem_list *m;
119
 
        
120
 
        for (m = *list; m; m = m->next) {
121
 
                if (m->p == p) {
122
 
                        void* tmp = m->p;
123
 
                        tmp = realloc(tmp, size);
 
118
        struct mem_list **m;
 
119
        struct mem_list *to_delete = NULL;
 
120
 
 
121
        for (m = list; *m; m = &(*m)->next)     {
 
122
                if ((*m)->p == p) {
 
123
                        void* tmp = p;
 
124
                        tmp = realloc(tmp, size);
 
125
                        if (size == 0)
 
126
                        {
 
127
                                /* The entry has been freed. Remove it from the list. */
 
128
                                to_delete = *m;
 
129
                                *m = to_delete->next;
 
130
                                if (to_delete->next != NULL)
 
131
                                {
 
132
                                        to_delete->next->prev = to_delete->prev;
 
133
                                }
 
134
                                free(to_delete);
 
135
                                return NULL;
 
136
                        }
124
137
                        if (!tmp) {
125
138
                                errno = ENOMEM;
126
139
                                return NULL;
127
140
                        }
128
 
                        m->p = tmp;
129
 
                        return m->p;
 
141
                        (*m)->p = tmp;
 
142
                        return tmp;
130
143
                }
131
144
        }
132
145
        errno = EINVAL;
1253
1266
        struct winbindd_response response;
1254
1267
        struct winbindd_request request;
1255
1268
        NSS_STATUS ret;
1256
 
        int i, idx;
 
1269
        size_t i, idx;
1257
1270
        char *tmpbuf;
1258
1271
        int num_gids;
1259
1272
        gid_t *gid_list;
1260
 
        char *r_user = user;
 
1273
        char *r_user = NULL;
 
1274
        FILE *groups_file = NULL;
 
1275
        size_t num_local_gids = 0;
 
1276
        size_t local_gid_list_capacity = 0;
 
1277
        gid_t *local_gid_list = NULL;
 
1278
        struct group group_buffer;
 
1279
        char *aux_buffer = NULL;
 
1280
        size_t aux_buffer_size = 2048;
 
1281
        int ret_errno = 0;
 
1282
        size_t member_index = 0;
1261
1283
        
1262
1284
        if (*user == WB_AIX_ENCODED) {
1263
 
                r_user = decode_user(r_user);
 
1285
                r_user = decode_user(user);
1264
1286
        }
 
1287
        else
 
1288
                r_user = user;
1265
1289
        
1266
1290
        logit_debug(LOG_DEBUG, "getgrset %s '%s'\n", user, r_user);
1267
1291
        
1268
1292
        if (!r_user) {
1269
 
                errno = ENOENT;
1270
 
                return NULL;
 
1293
                ret_errno = ENOENT;
 
1294
                goto cleanup;
1271
1295
        }
1272
1296
        
1273
 
        ZERO_STRUCT(response);
1274
 
        ZERO_STRUCT(request);
 
1297
        ZERO_STRUCT(response);
 
1298
        ZERO_STRUCT(request);
1275
1299
        
1276
1300
        STRCPY_RETNULL(request.data.username, r_user);
1277
1301
        
1278
 
        if (*user == WB_AIX_ENCODED) {
1279
 
                free(r_user);
1280
 
        }
1281
 
        
1282
1302
        ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
1283
1303
        
1284
1304
        HANDLE_ERRORS(ret);
1285
1305
        
1286
1306
        num_gids = response.data.num_entries;
1287
1307
        gid_list = (gid_t *)response.extra_data.data;
 
1308
 
 
1309
        /* Now search the local groups file to get a count of the local groups
 
1310
         * the user is a member of.
 
1311
         */
 
1312
        groups_file = fopen("/etc/group", "r");
 
1313
        if (groups_file != NULL)
 
1314
        {
 
1315
                aux_buffer = (char*) malloc(aux_buffer_size);
 
1316
                if (aux_buffer == NULL) {
 
1317
                        ret_errno = ENOMEM;
 
1318
                        goto cleanup;
 
1319
                }
 
1320
                while (1)
 
1321
                {
 
1322
                        /* There is no man page for fgetgrent_r on AIX. The Linux man page
 
1323
                         * says this function's last parameter is an out parameter for the
 
1324
                         * result, but on AIX it is an int which doesn't seem to be used
 
1325
                         * for anything, so I set it to 0.
 
1326
                         */
 
1327
                        ret_errno = fgetgrent_r(groups_file, &group_buffer,
 
1328
                                        aux_buffer, aux_buffer_size, 0);
 
1329
                        /* On Linux this function returns an errno value directly. On AIX,
 
1330
                         * it seems to return -1 and set the errno global.
 
1331
                         */
 
1332
                        if (ret_errno < 0)
 
1333
                        {
 
1334
                                ret_errno = errno;
 
1335
                        }
 
1336
                        /* On Linux, ENOENT is returned when no more results are
 
1337
                         * available. On AIX, ESRCH is returned.
 
1338
                         */
 
1339
                        if (ret_errno == ENOENT || ret_errno == ESRCH)
 
1340
                        {
 
1341
                                ret_errno = 0;
 
1342
                                break;
 
1343
                        }
 
1344
                        if (ret_errno == ERANGE || ret_errno == EINVAL)
 
1345
                        {
 
1346
                                /* The buffer is too small */
 
1347
                                if (aux_buffer_size > 1000000)
 
1348
                                {
 
1349
                                        /* We're not willing to give more space than that */
 
1350
                                        logit_debug(LOG_DEBUG,
 
1351
                                                        "fgetgrent_r is requesting too much memory\n");
 
1352
                                        ret_errno = ENOMEM;
 
1353
                                        goto cleanup;
 
1354
                                }
 
1355
                                free(aux_buffer);
 
1356
                                aux_buffer = NULL;
 
1357
                                aux_buffer_size *= 2;
 
1358
                                aux_buffer = (char*) malloc(aux_buffer_size);
 
1359
                                if (aux_buffer == NULL)
 
1360
                                {
 
1361
                                        ret_errno = ENOMEM;
 
1362
                                        goto cleanup;
 
1363
                                }
 
1364
                                ret_errno = 0;
 
1365
                                continue;
 
1366
                        }
 
1367
                        if (ret_errno != 0)
 
1368
                        {
 
1369
                                logit_debug(LOG_DEBUG,
 
1370
                                                "getgrset failed to enumerate local groups with error %d\n",
 
1371
                                                ret_errno);
 
1372
                                goto cleanup;
 
1373
                        }
 
1374
                        for (member_index = 0;
 
1375
                                group_buffer.gr_mem[member_index] != NULL;
 
1376
                                member_index++)
 
1377
                        {
 
1378
                                if (!strcmp(r_user, group_buffer.gr_mem[member_index]) ||
 
1379
                                        !strcmp(user, group_buffer.gr_mem[member_index]))
 
1380
                                {
 
1381
                                        /* Found a group */
 
1382
                                        if (num_local_gids >= local_gid_list_capacity)
 
1383
                                        {
 
1384
                                                local_gid_list_capacity += 10;
 
1385
                                                local_gid_list_capacity *= 2;
 
1386
                                                local_gid_list = (gid_t *)realloc(local_gid_list,
 
1387
                                                                local_gid_list_capacity * sizeof(gid_t));
 
1388
                                                if (local_gid_list == NULL)
 
1389
                                                {
 
1390
                                                        ret_errno = ENOMEM;
 
1391
                                                        goto cleanup;
 
1392
                                                }
 
1393
                                        }
 
1394
                                        local_gid_list[num_local_gids++] = group_buffer.gr_gid;
 
1395
                                        break;
 
1396
                                }
 
1397
                        }
 
1398
                }
 
1399
        }
1288
1400
        
1289
 
        /* allocate a space large enough to contruct the string */
1290
 
        tmpbuf = (char*) list_alloc(list, num_gids*12);
 
1401
        /* allocate a space large enough to construct the string */
 
1402
        tmpbuf = (char*) list_alloc(list, (num_gids + num_local_gids)*12);
1291
1403
        if (!tmpbuf) {
1292
 
                return NULL;
1293
 
        }
1294
 
 
1295
 
        for (idx=i=0; i < num_gids-1; i++) {
1296
 
                idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]); 
1297
 
        }
1298
 
        idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);  
 
1404
                ret_errno = ENOMEM;
 
1405
                goto cleanup;
 
1406
        }
 
1407
 
 
1408
        idx = 0;
 
1409
        for (i=0; i < num_gids; i++) {
 
1410
                if (idx > 0)
 
1411
                {
 
1412
                        tmpbuf[idx++]=',';
 
1413
                }
 
1414
                idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);  
 
1415
        }
 
1416
 
 
1417
        for (i=0; i < num_local_gids; i++) {
 
1418
                if (idx > 0)
 
1419
                {
 
1420
                        tmpbuf[idx++]=',';
 
1421
                }
 
1422
                idx += sprintf(tmpbuf+idx, "%u", local_gid_list[i]);    
 
1423
        }
 
1424
        tmpbuf[idx] = '\0';
 
1425
 
 
1426
cleanup:
 
1427
        if (groups_file != NULL)
 
1428
        {
 
1429
                fclose(groups_file);
 
1430
        }
1299
1431
 
1300
1432
        winbindd_free_response(&response);
1301
1433
 
 
1434
        if (*user == WB_AIX_ENCODED) {
 
1435
                free(r_user);
 
1436
        }
 
1437
 
 
1438
        if (local_gid_list != NULL) {
 
1439
                free(local_gid_list);
 
1440
        }
 
1441
        if (aux_buffer != NULL) {
 
1442
                free(aux_buffer);
 
1443
        }
 
1444
        if (ret_errno != 0)
 
1445
        {
 
1446
                if(tmpbuf != NULL)
 
1447
                {
 
1448
                        list_realloc(list, tmpbuf, 0);
 
1449
                        tmpbuf = NULL;
 
1450
                }
 
1451
                errno = ret_errno;
 
1452
        }
 
1453
 
1302
1454
        return tmpbuf;
1303
1455
}
1304
1456
 
1537
1689
        return r;
1538
1690
}
1539
1691
 
 
1692
static int local_getgrgid_r(gid_t gid, struct group *group_buffer,
 
1693
                char *aux_buffer, size_t aux_buffer_size, struct group **result)
 
1694
{
 
1695
        size_t i, idx;
 
1696
        FILE *groups_file = NULL;
 
1697
        int error;
 
1698
        
 
1699
        /* Now search the local groups file to get a count of the local groups
 
1700
         * the user is a member of.
 
1701
         */
 
1702
        groups_file = fopen("/etc/group", "r");
 
1703
        if (groups_file != NULL)
 
1704
        {
 
1705
                while (1)
 
1706
                {
 
1707
                        /* There is no man page for fgetgrent_r on AIX. The Linux man page
 
1708
                         * says this function's last parameter is an out parameter for the
 
1709
                         * result, but on AIX it is an int which doesn't seem to be used
 
1710
                         * for anything, so I set it to 0.
 
1711
                         */
 
1712
                        error = fgetgrent_r(groups_file, group_buffer,
 
1713
                                        aux_buffer, aux_buffer_size, 0);
 
1714
                        /* On Linux this function returns an errno value directly. On AIX,
 
1715
                         * it seems to return -1 and set the errno global.
 
1716
                         */
 
1717
                        if (error < 0)
 
1718
                        {
 
1719
                                error = errno;
 
1720
                        }
 
1721
                        /* On Linux, ENOENT is returned when no more results are
 
1722
                         * available. On AIX, ESRCH is returned.
 
1723
                         */
 
1724
                        if (error != 0)
 
1725
                        {
 
1726
                                goto cleanup;
 
1727
                        }
 
1728
                        if (group_buffer->gr_gid == gid)
 
1729
                        {
 
1730
                                *result = group_buffer;
 
1731
                                error = 0;
 
1732
                                goto cleanup;
 
1733
                        }
 
1734
                }
 
1735
        }
 
1736
        error = errno;
 
1737
 
 
1738
cleanup:
 
1739
        if (groups_file != NULL)
 
1740
        {
 
1741
                fclose(groups_file);
 
1742
        }
 
1743
        return error;
 
1744
}
 
1745
 
1540
1746
static attrval_t pwd_to_groupsnames(struct mem_list** mlist, struct passwd *pwd)
1541
1747
{
1542
1748
        attrval_t r;
1547
1753
        char *s = NULL;
1548
1754
        char *p = NULL;
1549
1755
        char *gid = NULL;
1550
 
        struct group *group = NULL;
 
1756
        struct group *group;
 
1757
        struct group group_buffer;
 
1758
        char aux_buffer[2048];
 
1759
        struct mem_list* local_list_buffer = 0;
 
1760
        struct mem_list** local_list = &local_list_buffer;
1551
1761
 
1552
 
        if ( (s = __wb_aix_getgrset(mlist, pwd->pw_name)) == NULL ) {
 
1762
        if ( (s = __wb_aix_getgrset(local_list, pwd->pw_name)) == NULL ) {
1553
1763
                r.attr_flag = EINVAL;
1554
 
                return r;
 
1764
                goto cleanup;
1555
1765
        }
1556
1766
 
1557
1767
        list = (char *)list_alloc(mlist, buf_current_size + 1);
1558
1768
        if (!list) {  
1559
 
                //SAFE_FREE(s);
1560
1769
                errno = ENOMEM;
1561
1770
                r.attr_flag = ENOMEM;
1562
 
                return r;
 
1771
                goto cleanup;
1563
1772
         }
1564
1773
 
1565
1774
        /* Walk the list of group id's and find the group name for each */
1567
1776
             gid; 
1568
1777
             gid = strtok_r(NULL, ",", &p)) {
1569
1778
                
1570
 
                group = __wb_aix_getgrgid(mlist, strtoul(gid, NULL, 10));
 
1779
                group = __wb_aix_getgrgid(local_list, strtoul(gid, NULL, 10));
1571
1780
                
 
1781
                if (group == NULL)
 
1782
                {
 
1783
                        local_getgrgid_r(strtoul(gid, NULL, 10), &group_buffer,
 
1784
                                        aux_buffer, sizeof(aux_buffer), &group);
 
1785
                }
 
1786
                if (group == NULL)
 
1787
                {
 
1788
                        logit_debug(LOG_DEBUG, "Unable to lookup group id %s\n", gid);
 
1789
                        continue;
 
1790
                }
1572
1791
                len = strlen(group->gr_name); 
1573
1792
                
1574
1793
                /* See if we have enought memory */ 
1577
1796
                        buf_current_size += len + 1;
1578
1797
                        list = (char*)list_realloc(mlist, list, buf_current_size);
1579
1798
                        if(!list) {
1580
 
                                SAFE_FREE(group);
1581
1799
                                errno = ENOMEM;
1582
1800
                                r.attr_flag = ENOMEM;
1583
 
                                return r;
 
1801
                                goto cleanup;
1584
1802
                        }
1585
1803
                }
1586
1804
                
1587
1805
                strcpy(list + buf_used, group->gr_name);
1588
1806
                buf_used += len + 1;
1589
 
                
1590
 
                SAFE_FREE(group);
1591
1807
        }
1592
 
        
 
1808
 
1593
1809
        /* Terminate list - we now have each element in the list separted by a single '/0'
1594
1810
           with the end of the list having a double '/0' */
1595
1811
        list[buf_used] = '\0';
1602
1818
        r.attr_flag = 0;
1603
1819
        r.attr_un.au_char = list;
1604
1820
        
 
1821
cleanup:
 
1822
        list_destroy(&local_list_buffer);
1605
1823
        return r;
1606
1824
}
1607
1825