2 * Copyright (C) 2017 "IoT.bzh"
3 * Author: José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
25 #include <sys/types.h>
26 #include <sys/socket.h>
30 #define MAX_LABEL_LENGTH 1024
32 static struct afb_cred *current;
34 static struct afb_cred *mkcred(uid_t uid, gid_t gid, pid_t pid, const char *label, size_t size)
36 struct afb_cred *cred;
44 user[i++] = (char)('0' + u % 10);
46 } while(u && i < sizeof user);
48 cred = malloc(2 + i + size + sizeof *cred);
56 dest = (char*)(&cred[1]);
63 memcpy(dest, label, size);
65 dest = strrchr(dest, ':');
72 static struct afb_cred *mkcurrent()
74 char label[MAX_LABEL_LENGTH];
78 fd = open("/proc/self/attr/current", O_RDONLY);
82 rc = read(fd, label, sizeof label);
88 return mkcred(getuid(), getgid(), getpid(), label, (size_t)rc);
91 struct afb_cred *afb_cred_create(uid_t uid, gid_t gid, pid_t pid, const char *label)
94 return mkcred(uid, gid, pid, label, strlen(label));
97 struct afb_cred *afb_cred_create_for_socket(int fd)
102 char label[MAX_LABEL_LENGTH];
104 /* get the credentials */
105 length = (socklen_t)(sizeof ucred);
106 rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &length);
107 if (rc < 0 || length != (socklen_t)(sizeof ucred)) {
113 /* get the security label */
114 length = (socklen_t)(sizeof label);
115 rc = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, label, &length);
116 if (rc < 0 || length > (socklen_t)(sizeof label)) {
122 /* makes the result */
123 return mkcred(ucred.uid, ucred.gid, ucred.pid, label, (size_t)length);
126 struct afb_cred *afb_cred_addref(struct afb_cred *cred)
129 __atomic_add_fetch(&cred->refcount, 1, __ATOMIC_RELAXED);
133 void afb_cred_unref(struct afb_cred *cred)
135 if (cred && !__atomic_sub_fetch(&cred->refcount, 1, __ATOMIC_RELAXED)) {
143 struct afb_cred *afb_cred_current()
146 current = mkcurrent();
147 return afb_cred_addref(current);