This function loads the ACL from the specified filename: every line * is validated and should be either empty or in the format used to specify * users in the keydb.conf configuration or in the ACL file, that is: * * user ... rules ... * * Note that this function considers comments starting with '#' as errors * because the ACL file is meant to be rewritten, and comments would be
| 1509 | * NULL is returned. Otherwise an SDS string describing in a single line |
| 1510 | * a description of all the issues found is returned. */ |
| 1511 | sds ACLLoadFromFile(const char *filename) { |
| 1512 | FILE *fp; |
| 1513 | char buf[1024]; |
| 1514 | |
| 1515 | /* Open the ACL file. */ |
| 1516 | if ((fp = fopen(filename,"r")) == NULL) { |
| 1517 | sds errors = sdscatprintf(sdsempty(), |
| 1518 | "Error loading ACLs, opening file '%s': %s", |
| 1519 | filename, strerror(errno)); |
| 1520 | return errors; |
| 1521 | } |
| 1522 | |
| 1523 | /* Load the whole file as a single string in memory. */ |
| 1524 | sds acls = sdsempty(); |
| 1525 | while(fgets(buf,sizeof(buf),fp) != NULL) |
| 1526 | acls = sdscat(acls,buf); |
| 1527 | fclose(fp); |
| 1528 | |
| 1529 | /* Split the file into lines and attempt to load each line. */ |
| 1530 | int totlines; |
| 1531 | sds *lines, errors = sdsempty(); |
| 1532 | lines = sdssplitlen(acls,strlen(acls),"\n",1,&totlines); |
| 1533 | sdsfree(acls); |
| 1534 | |
| 1535 | /* We need a fake user to validate the rules before making changes |
| 1536 | * to the real user mentioned in the ACL line. */ |
| 1537 | user *fakeuser = ACLCreateUnlinkedUser(); |
| 1538 | |
| 1539 | /* We do all the loading in a fresh instance of the Users radix tree, |
| 1540 | * so if there are errors loading the ACL file we can rollback to the |
| 1541 | * old version. */ |
| 1542 | rax *old_users = Users; |
| 1543 | user *old_default_user = DefaultUser; |
| 1544 | Users = raxNew(); |
| 1545 | ACLInitDefaultUser(); |
| 1546 | |
| 1547 | /* Load each line of the file. */ |
| 1548 | for (int i = 0; i < totlines; i++) { |
| 1549 | sds *argv; |
| 1550 | int argc; |
| 1551 | int linenum = i+1; |
| 1552 | |
| 1553 | lines[i] = sdstrim(lines[i]," \t\r\n"); |
| 1554 | |
| 1555 | /* Skip blank lines */ |
| 1556 | if (lines[i][0] == '\0') continue; |
| 1557 | |
| 1558 | /* Split into arguments */ |
| 1559 | argv = sdssplitlen(lines[i],sdslen(lines[i])," ",1,&argc); |
| 1560 | if (argv == NULL) { |
| 1561 | errors = sdscatprintf(errors, |
| 1562 | "%s:%d: unbalanced quotes in acl line. ", |
| 1563 | g_pserver->acl_filename, linenum); |
| 1564 | continue; |
| 1565 | } |
| 1566 | |
| 1567 | /* Skip this line if the resulting command vector is empty. */ |
| 1568 | if (argc == 0) { |
no test coverage detected