mirror of
https://github.com/mabam/afpfs-ng-mac.git
synced 2025-01-30 06:32:02 +00:00
154 lines
3.6 KiB
C
154 lines
3.6 KiB
C
#include <stdlib.h>
|
|
#include <pwd.h>
|
|
#include <grp.h>
|
|
#include <string.h>
|
|
|
|
#include "afpfs-ng/afp.h"
|
|
#include "afpfs-ng/map_def.h"
|
|
|
|
/* How mapping works
|
|
*
|
|
* There are 3 kinds of user/group mapping:
|
|
*
|
|
* 1. Common user directory
|
|
*
|
|
* This is where the client and server share the same user/group database.
|
|
* An example of this is where NIS is used.
|
|
*
|
|
* 2. Login ids
|
|
*
|
|
* This is where all the files appear as the user that logged in. This would
|
|
* typically be used where the databases are separate, and one user expects to
|
|
* be able to read/write all the files he sees. This can get confusing, since
|
|
* any files that aren't his will appear to be owned by him, but writing to
|
|
* them will result in an EPERM.
|
|
*
|
|
* 3. Name mapped
|
|
*
|
|
* All the uid/gid translation is done based on usernames.
|
|
*
|
|
* This is currently unsupported.
|
|
*
|
|
*/
|
|
|
|
int translate_uidgid_to_server(struct afp_volume * volume,
|
|
unsigned int * newuid, unsigned int *newgid)
|
|
{
|
|
switch(volume->mapping) {
|
|
case AFP_MAPPING_COMMON:
|
|
/* The user databases are the same, don't do
|
|
* any translaion. */
|
|
break;
|
|
case AFP_MAPPING_LOGINIDS:
|
|
/* Return the value of what we used when we
|
|
logged in.*/
|
|
|
|
*newuid=volume->server->server_uid;
|
|
*newgid=volume->server->server_gid;
|
|
break;
|
|
default:
|
|
case AFP_MAPPING_UNKNOWN:
|
|
return -1;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int translate_uidgid_to_client(struct afp_volume * volume,
|
|
unsigned int * newuid, unsigned int *newgid)
|
|
{
|
|
switch(volume->mapping) {
|
|
case AFP_MAPPING_COMMON:
|
|
/* The user databases are the same, don't do
|
|
* any translaion. */
|
|
break;
|
|
case AFP_MAPPING_LOGINIDS:
|
|
/* This is the case where we always return the uid/gid
|
|
* of the user who ran afpfsd.
|
|
*/
|
|
*newuid=volume->server->passwd.pw_uid;
|
|
*newgid=volume->server->passwd.pw_gid;
|
|
break;
|
|
default:
|
|
case AFP_MAPPING_UNKNOWN:
|
|
return -1;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int afp_detect_mapping(struct afp_volume * volume)
|
|
{
|
|
char name[255];
|
|
struct passwd * passwd_entry;
|
|
unsigned int dummy;
|
|
unsigned int tmpgid;
|
|
|
|
/* See if it is already set. This is typically when the client
|
|
* requested a specific mapping. */
|
|
|
|
if (volume->mapping != AFP_MAPPING_UNKNOWN)
|
|
return 0;
|
|
|
|
if ((volume->attributes & kNoNetworkUserIDs) ) {
|
|
volume->mapping = AFP_MAPPING_LOGINIDS;
|
|
return 0;
|
|
}
|
|
/* Check to see if the user databases appear to be synchronous.
|
|
* This is done based on the algorithm specified on p.20.
|
|
*/
|
|
|
|
/* By default, we're in AFP_MAPPING_LOGINIDS. */
|
|
|
|
volume->mapping = AFP_MAPPING_LOGINIDS;
|
|
volume->server->server_gid_valid=0;
|
|
|
|
/* 1. call getuid */
|
|
|
|
passwd_entry=&volume->server->passwd;
|
|
|
|
/* 2. Send FPGetUserInfo to get the user's uid */
|
|
|
|
if (afp_getuserinfo(volume->server, 1, /* this user */
|
|
0, /* Irrelevant since we're getting the info for ThisUser */
|
|
kFPGetUserInfo_USER_ID,
|
|
&volume->server->server_uid,
|
|
&dummy))
|
|
return 0;
|
|
|
|
/* In the past, this has not worked for some versions of Mac OS, but
|
|
* this hasn't been fully verified */
|
|
if (afp_getuserinfo(volume->server, 1, /* this user */
|
|
0,
|
|
kFPGetUserInfo_PRI_GROUPID, &dummy,
|
|
&tmpgid)==0) {
|
|
volume->server->server_gid_valid=1;
|
|
volume->server->server_gid=tmpgid;
|
|
}
|
|
|
|
/* 3. If they match, call getpwuid to get the local user name */
|
|
|
|
if (volume->server->server_uid!=passwd_entry->pw_uid)
|
|
return 0;
|
|
|
|
/* 4. send an FPMapID to get the user's username. */
|
|
|
|
afp_mapid(volume->server,
|
|
(volume->attributes & kSupportsUTF8Names)
|
|
? kUserIDToUTF8Name : kUserIDToName,
|
|
passwd_entry->pw_uid,name);
|
|
|
|
|
|
/* 5. If they match, we're in AFP_MAPPING_COMMON mode. */
|
|
|
|
if (strcmp(name,passwd_entry->pw_name)==0)
|
|
volume->mapping = AFP_MAPPING_COMMON;
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|