1 // Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2 // This Source Code Form is subject to the terms of the Mozilla Public
3 // License, v. 2.0. If a copy of the MPL was not distributed with this
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
6 #ifndef _WIN32
7
8 #include <sys/socket.h>
9
10 #include "../include/credentials.hpp"
11
12 #include <vsomeip/internal/logger.hpp>
13 #ifdef ANDROID
14 #include "../../configuration/include/internal_android.hpp"
15 #else
16 #include "../../configuration/include/internal.hpp"
17 #endif
18
19 namespace vsomeip_v3 {
20
activate_credentials(const int _fd)21 void credentials::activate_credentials(const int _fd) {
22 int optval = 1;
23 if (setsockopt(_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
24 VSOMEIP_ERROR << "vSomeIP Security: Activating socket option for receiving "
25 << "credentials failed.";
26 }
27 }
28
deactivate_credentials(const int _fd)29 void credentials::deactivate_credentials(const int _fd) {
30 int optval = 0;
31 if (setsockopt(_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
32 VSOMEIP_ERROR << "vSomeIP Security: Deactivating socket option for receiving "
33 << "credentials failed.";
34 }
35 }
36
receive_credentials(const int _fd,uid_t & _uid,gid_t & _gid)37 client_t credentials::receive_credentials(const int _fd, uid_t& _uid, gid_t& _gid) {
38 struct ucred *ucredp;
39 struct msghdr msgh;
40 struct iovec iov;
41 union {
42 struct cmsghdr cmh;
43 char control[CMSG_SPACE(sizeof(struct ucred))];
44 } control_un;
45 struct cmsghdr *cmhp;
46 // Sender client_id will be received as data
47 client_t client = VSOMEIP_ROUTING_CLIENT;
48
49 // Set 'control_un' to describe ancillary data that we want to receive
50 control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
51 control_un.cmh.cmsg_level = SOL_SOCKET;
52 control_un.cmh.cmsg_type = SCM_CREDENTIALS;
53
54 // Set 'msgh' fields to describe 'control_un'
55 msgh.msg_control = control_un.control;
56 msgh.msg_controllen = sizeof(control_un.control);
57
58 // Set fields of 'msgh' to point to buffer used to receive (real) data read by recvmsg()
59 msgh.msg_iov = &iov;
60 msgh.msg_iovlen = 1;
61 iov.iov_base = &client;
62 iov.iov_len = sizeof(client_t);
63
64 // We don't need address of peer as we using connect
65 msgh.msg_name = NULL;
66 msgh.msg_namelen = 0;
67
68 // Receive client_id plus ancillary data
69 ssize_t nr = recvmsg(_fd, &msgh, 0);
70 if (nr == -1) {
71 VSOMEIP_ERROR << "vSomeIP Security: Receiving credentials failed. No data.";
72 }
73
74 cmhp = CMSG_FIRSTHDR(&msgh);
75 if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(struct ucred))
76 || cmhp->cmsg_level != SOL_SOCKET || cmhp->cmsg_type != SCM_CREDENTIALS) {
77 VSOMEIP_ERROR << "vSomeIP Security: Receiving credentials failed. Invalid data.";
78 } else {
79 ucredp = (struct ucred *) CMSG_DATA(cmhp);
80 _uid = ucredp->uid;
81 _gid = ucredp->gid;
82 }
83
84 return client;
85 }
86
send_credentials(const int _fd,client_t _client)87 void credentials::send_credentials(const int _fd, client_t _client) {
88 struct msghdr msgh;
89 struct iovec iov;
90
91 // data to send
92 msgh.msg_iov = &iov;
93 msgh.msg_iovlen = 1;
94 iov.iov_base = &_client;
95 iov.iov_len = sizeof(client_t);
96
97 // destination not needed as we use connect
98 msgh.msg_name = NULL;
99 msgh.msg_namelen = 0;
100
101 // credentials not need to set explicitly
102 msgh.msg_control = NULL;
103 msgh.msg_controllen = 0;
104
105 // send client id with credentials
106 ssize_t ns = sendmsg(_fd, &msgh, 0);
107 if (ns == -1) {
108 VSOMEIP_ERROR << "Sending credentials failed.";
109 }
110 }
111
112 } // namespace vsomeip_v3
113
114 #endif // #ifndef _WIN32
115
116