blob: 4fcc0a9b0188722e2eaca2499db8d99a999b354e [file] [log] [blame]
Weiweie5640c62015-07-31 01:43:01 -07001# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2#
3# Copyright (C) 2014-2015 Regents of the University of California.
4# Author: Weiwei Liu <summerwing10@gmail.com>
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU Lesser General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU Lesser General Public License for more details.
15#
16# You should have received a copy of the GNU Lesser General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18# A copy of the GNU Lesser General Public License is in the file COPYING.
19
20"""
21This module defines the DeviceUserAccessManager class which is the interface of
22operations related to identity, keys, and certificates.
23"""
24
25import sys
Weiwei074778b2015-08-07 21:30:44 -070026import hmac
27from hashlib import sha256
Weiweie5640c62015-07-31 01:43:01 -070028from pyndn.name import Name
29from device_profile import DeviceProfile
Weiweif3132ed2015-08-05 11:20:49 -070030from device_storage import DeviceStorage
Weiwei074778b2015-08-07 21:30:44 -070031from hmac_key import HMACKey
32from user_access_storage import UserAccessStorage
Weiweie5640c62015-07-31 01:43:01 -070033
34class DeviceUserAccessManager(object):
35 """
36 Create a new DeviceUserAccessManager
37 """
38 def __init__(self, databaseFilePath = None):
Weiwei074778b2015-08-07 21:30:44 -070039 deviceStorage = DeviceStorage(databaseFilePath)
40 self._deviceStorage = deviceStorage
41 userAccessStorage = UserAccessStorage(databaseFilePath)
42 self._userAccessStorage = userAccessStorage
43
Weiweie5640c62015-07-31 01:43:01 -070044 def createDevice(self, deviceProfile, seed, configurationToken, commandList = None):
45 """
46 Create a device in the database, including it's corresponding commands and serrvice profiles
47 @param DeviceProfile deviceProfile: the device profile
48 @param SymmetricKey seed: the seed of the device
49 @param SymmetricKey configurationToken: the configuration Token of the device
50 @param list commandList: the command list of the device, must have following structure: each element in the list should be a two-tuple (commandName, commandToken), the commandName should be a string, and commandToken should be a SymmetricKey. Here is an example of a valid commandList : [('turn_on', commandToken1), ('turn_off', commandToken2)]
51 return True if succeed, otherwise False
52 """
53 result = False
54
55 #add device
Weiwei074778b2015-08-07 21:30:44 -070056 deviceId = self._deviceStorage.addDevice(deviceProfile, seed, configurationToken)
Weiweie5640c62015-07-31 01:43:01 -070057 if deviceId == 0:
58 raise RuntimeError("device already exists in database")
59 return result
60 elif deviceId == -1:
61 raise RuntimeError("error occured during adding device into database")
62 return result
63
64 #add service profile
65 serviceProfileList = deviceProfile.getServiceProfileList()
66 for serviceProfileName in serviceProfileList:
Weiwei074778b2015-08-07 21:30:44 -070067 serviceProfileId = self._deviceStorage.addServiceProfile(deviceId, serviceProfileName)
Weiweie5640c62015-07-31 01:43:01 -070068 if serviceProfileId == 0:
69 raise RuntimeError("service profile: " + serviceProfileName + " already exists in database")
70 return result
71 elif serviceProfileId == -1:
72 raise RuntimeError("error occured during adding service profile :" + serviceProfileName)
73 return result
Weiwei074778b2015-08-07 21:30:44 -070074
Weiweie5640c62015-07-31 01:43:01 -070075 #add command
Weiwei074778b2015-08-07 21:30:44 -070076 for command in commandList:
77 #generate command token,firstt generate command token name
78 prefix = deviceProfile.getPrefix()
79 commandTokenName = prefix.toUri()+"/"+command+"/token/0"
80 commandTokenKey = hmac.new(seed.getKey(), commandTokenName,sha256).digest()
81 commandToken = HMACKey(0,0,commandTokenKey,commandTokenName)
82
83 commandId = self._deviceStorage.addCommand(deviceId, command, commandToken)
Weiweie5640c62015-07-31 01:43:01 -070084 if commandId == 0:
85 raise RuntimeError("command: " + commandTuple[0] + " already exists in database")
86 return result
87 elif commandId == -1:
88 raise RuntimeError("error occured during adding command:" +commandTuple[0])
89 return result
90 result = True
91 return result
92
93 def getDeviceProfile(self, prefix):
94 """
95 get device profile of a specified device
96 :param Name prefix: the device prefix
97 :return device profile of the device if exists, otherwise return None
98 :rtype: DeviceProfile
99 """
Weiwei074778b2015-08-07 21:30:44 -0700100 deviceProfile = self._deviceStorage.getDeviceProfileFromDevice(prefix)
Weiweie5640c62015-07-31 01:43:01 -0700101 if deviceProfile == None:
102 return deviceProfile
103 else:
104 # get device Id
Weiwei074778b2015-08-07 21:30:44 -0700105 deviceId = self._deviceStorage.getDeviceId(deviceProfile.getPrefix())
Weiweie5640c62015-07-31 01:43:01 -0700106 if deviceId == 0:
107 raise RuntimeError("device doesn't exist")
108
Weiwei074778b2015-08-07 21:30:44 -0700109 serviceProfileList = self._deviceStorage.getServiceProfilesOfDevice(deviceId)
Weiweie5640c62015-07-31 01:43:01 -0700110 deviceProfile.setServiceProfile(serviceProfileList)
111
112 return deviceProfile
113
114 def getSeed(self, prefix):
115 """
116 get seed of a specified device
117 :param Name prefix: the device prefix
118 :return seed of the device if exists, otherwise return None
119 :rtype: SymmetricKey
120 """
Weiwei074778b2015-08-07 21:30:44 -0700121 return self._deviceStorage.getSeed(prefix)
Weiweie5640c62015-07-31 01:43:01 -0700122
123 def getConfigurationToken(self, prefix):
124 """
125 get configuration token of a specified device
126 :param Name prefix: the device prefix
127 :return seed of the device if exists, otherwise return None
128 :rtype: SymmetricKey
129 """
Weiwei074778b2015-08-07 21:30:44 -0700130 return self._deviceStorage.getConfigurationToken(prefix)
Weiweie5640c62015-07-31 01:43:01 -0700131
132 def getCommandToken(self, prefix, commandName):
133 """
134 get command token of a specified command
135 :param Name prefix: the device prefix
136 :param str commandName: device name of the command
137 :return command token if command existsm, otherwise None
138 :rtype SymmetricKey
139 """
Weiwei074778b2015-08-07 21:30:44 -0700140 deviceId = self._deviceStorage.getDeviceId(prefix)
Weiweie5640c62015-07-31 01:43:01 -0700141 if deviceId == 0:
142 return None
Weiwei074778b2015-08-07 21:30:44 -0700143 return self._deviceStorage.getCommandToken(deviceId, commandName)
Weiweie5640c62015-07-31 01:43:01 -0700144
145 def getCommandsOfDevice(self, prefix):
146 """
147 get all the commands of a specified device
148 :param Name prefix: the device prefix
149 :return command name list if any commands exist, otherwise None
150 """
Weiwei074778b2015-08-07 21:30:44 -0700151 deviceId = self._deviceStorage.getDeviceId(prefix)
Weiweie5640c62015-07-31 01:43:01 -0700152 if deviceId == 0:
153 return None
Weiwei074778b2015-08-07 21:30:44 -0700154 return self._deviceStorage.getCommandsOfDevice(deviceId)
Weiweie5640c62015-07-31 01:43:01 -0700155
156 def getServiceProfilesOfDevice(self, prefix):
157 """
158 get all the service profiles of a specified device
159 :param Name prefix: the device prefix
160 :return service profiles name list if any service profiles exist, otherwise None
161 """
Weiwei074778b2015-08-07 21:30:44 -0700162 deviceId = self._deviceStorage.getDeviceId(prefix)
Weiweie5640c62015-07-31 01:43:01 -0700163 if deviceId == 0:
164 return None
Weiwei074778b2015-08-07 21:30:44 -0700165 return self._deviceStorage.getServiceProfilesOfDevice(deviceId)
166
167 def addUser(self, prefix, username, hash_, salt, type_):
168 """
169 Add a new user to User table, do nothing if the user already exists
170
171 :param Name prefix: the prefix of the user
172 :param str username: username
173 :param hash_:
174 :param salt:
175 :param str type: the type of user, either guest or user
176 :return the user id if it's added successfully, 0 if prefix conflict exists, -1 if username conflict exists
177 :rtype: INTEGER
178 """
179 return self._userAccessStorage.addUser(prefix, username, hash_, salt, type_)
180
181 def addAccess(self, devicePrefix, commandName, userPrefix, userDevice, accessToken):
182 """
183 Add a new access to the Access table, do nothing if the access already exists
184 :param Name devicePrefix: the device prefix
185 :param str command name : the command name
186 :param Name userPrefix: the user prefix
187 :param int userDevice: the user device
188 :param HMACKey accessToken: the access token
189 :return the access id if it's added successfully, 0 if the access already exists, otherwise -1
190 :rtype: int
191 """
192 #get device Id
193 deviceId = self._deviceStorage.getDeviceId(devicePrefix)
194 if deviceId == 0:
195 print 1
196 return -1
197
198 #get command id
199 commandId = self._deviceStorage.getCommandId(deviceId, commandName)
200 if commandId == 0:
201 print 2
202 return -1
203
204 #get user id
205 userId = self._userAccessStorage.getUserId(userPrefix)
206 if userId ==0:
207 print 3
208 return -1
209
210 return self._userAccessStorage.addAccess(commandId, userId, userDevice, accessToken)
211
212 def getAccessInfo(self, userPrefix, devicePrefix):
213 """
214 get all aceess info for pair(user, device)
215 :param Name userPrefix: the prefix of user
216 :param Name devicePrefix: the prefix of device
217 :return a list of tuples of form (str commandName,str userDevice, HmacKey accessToken). e.g. [('turn_on','laptop'. AccessToken1), ('turn_off','laptop' AccessToken2)], return None if no such access exists
218 :rtype list
219 """
220 #get device Id
221 deviceId = self._deviceStorage.getDeviceId(devicePrefix)
222
223 #get user Id
224 userId = self._userAccessStorage.getUserId(userPrefix)
225
226 if userId <= 0 or deviceId <= 0:
227 #either user or device doesn't exist in table
228 return None
229
230 #get command id list of device
231 commandIdList = self._deviceStorage.getCommandIdsOfDevice(deviceId)
232 if commandIdList == []:
233 return None
234
235 accessList =[]
236 for commandId in commandIdList:
237 doesExist = self._userAccessStorage.doesAccessExist(commandId, userId)
238 if doesExist:
239 commandName = self._deviceStorage.getCommandNameFromId(commandId)
240 userDeviceList = self._userAccessStorage.getUserDevices(commandId, userId)
241 for userDevice in userDeviceList:
242 accessToken = self._userAccessStorage.getAccessToken(commandId, userId, userDevice)
243 accessTuple = (commandName, userDevice, accessToken)
244 accessList.append(accessTuple)
245
246 return accessList