1 /*
2  * Copyright (C) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *    http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "account_unrelated_group_auth.h"
17 #include "common_defs.h"
18 #include "compatible_auth_sub_session_common.h"
19 #include "device_auth_defines.h"
20 #include "group_auth_data_operation.h"
21 #include "hc_log.h"
22 #include "hc_time.h"
23 #include "hc_types.h"
24 #include "json_utils.h"
25 #include "os_account_adapter.h"
26 #include "performance_dumper.h"
27 #include "string_util.h"
28 #include "hisysevent_adapter.h"
29 
30 static void OnDasFinish(int64_t requestId, const CJson *authParam, const CJson *out,
31     const DeviceAuthCallback *callback);
32 static int32_t FillNonAccountAuthInfo(int32_t osAccountId, const TrustedGroupEntry *entry,
33     const TrustedDeviceEntry *localAuthInfo, CJson *paramsData);
34 static int32_t GetAuthParamsVecForServer(const CJson *dataFromClient, ParamsVecForAuth *authParamsVec);
35 static int32_t CombineDasServerConfirmParams(const CJson *confirmationJson, CJson *dataFromClient);
36 
37 static NonAccountGroupAuth g_nonAccountGroupAuth = {
38     .base.onFinish = OnDasFinish,
39     .base.fillDeviceAuthInfo = FillNonAccountAuthInfo,
40     .base.getAuthParamsVecForServer = GetAuthParamsVecForServer,
41     .base.combineServerConfirmParams = CombineDasServerConfirmParams,
42     .base.authType = ACCOUNT_UNRELATED_GROUP_AUTH_TYPE,
43 };
44 
ReturnSessionKey(int64_t requestId,const CJson * out,const DeviceAuthCallback * callback)45 static int32_t ReturnSessionKey(int64_t requestId, const CJson *out, const DeviceAuthCallback *callback)
46 {
47     const char *returnSessionKeyStr = GetStringFromJson(out, FIELD_SESSION_KEY);
48     if (returnSessionKeyStr == NULL) {
49         LOGE("Failed to get sessionKey!");
50         return HC_ERR_JSON_GET;
51     }
52     uint32_t keyLen = (HcStrlen(returnSessionKeyStr) / BYTE_TO_HEX_OPER_LENGTH);
53     uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0);
54     if (sessionKey == NULL) {
55         LOGE("Failed to allocate memory for sessionKey!");
56         return HC_ERR_ALLOC_MEMORY;
57     }
58 
59     int32_t res = HC_SUCCESS;
60     do {
61         if (GetByteFromJson(out, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) {
62             LOGE("Failed to get sessionKey!");
63             res = HC_ERR_JSON_GET;
64             break;
65         }
66         if ((callback == NULL) || (callback->onSessionKeyReturned == NULL)) {
67             LOGE("The callback of onSessionKeyReturned is null!");
68             res = HC_ERR_INVALID_PARAMS;
69             break;
70         }
71         LOGI("Begin invoke onSessionKeyReturned.");
72         UPDATE_PERFORM_DATA_BY_INPUT_INDEX(requestId, ON_SESSION_KEY_RETURN_TIME, HcGetCurTimeInMillis());
73         callback->onSessionKeyReturned(requestId, sessionKey, keyLen);
74         LOGI("End invoke onSessionKeyReturned, res = %d.", res);
75     } while (0);
76     (void)memset_s(sessionKey, keyLen, 0, keyLen);
77     HcFree(sessionKey);
78     sessionKey = NULL;
79     return res;
80 }
81 
AddGroupIdToSelfData(const CJson * authParam,CJson * returnToSelf)82 static int32_t AddGroupIdToSelfData(const CJson *authParam, CJson *returnToSelf)
83 {
84     const char *groupId = GetStringFromJson(authParam, FIELD_SERVICE_TYPE);
85     if (groupId == NULL) {
86         LOGE("Failed to get groupId from authParam!");
87         return HC_ERR_JSON_GET;
88     }
89     if (AddStringToJson(returnToSelf, FIELD_GROUP_ID, groupId) != HC_SUCCESS) {
90         LOGE("Failed to add group id!");
91         return HC_ERR_JSON_FAIL;
92     }
93     return HC_SUCCESS;
94 }
95 
AddPeerUdidToSelfData(const CJson * authParam,CJson * returnToSelf)96 static int32_t AddPeerUdidToSelfData(const CJson *authParam, CJson *returnToSelf)
97 {
98     const char *peerUdid = GetStringFromJson(authParam, FIELD_PEER_CONN_DEVICE_ID);
99     if (peerUdid == NULL) {
100         LOGD("The input has no peerUdid in authParam!");
101         return HC_SUCCESS;
102     }
103     if (AddStringToJson(returnToSelf, FIELD_PEER_CONN_DEVICE_ID, peerUdid) != HC_SUCCESS) {
104         LOGE("Failed to add peer udid!");
105         return HC_ERR_JSON_FAIL;
106     }
107     return HC_SUCCESS;
108 }
109 
AddPeerAuthIdToSelfData(const CJson * authParam,CJson * returnToSelf)110 static int32_t AddPeerAuthIdToSelfData(const CJson *authParam, CJson *returnToSelf)
111 {
112     const char *peerAuthId = GetStringFromJson(authParam, FIELD_PEER_AUTH_ID);
113     if (peerAuthId == NULL) {
114         LOGD("No peerAuthId in auth session cached params!");
115         return HC_SUCCESS;
116     }
117 
118     if (AddStringToJson(returnToSelf, FIELD_PEER_AUTH_ID, peerAuthId) != HC_SUCCESS) {
119         LOGE("Failed to add peerAuthId!");
120         return HC_ERR_JSON_FAIL;
121     }
122     return HC_SUCCESS;
123 }
124 
AddSelfTypeToSelfData(const CJson * authParam,CJson * returnToSelf)125 static int32_t AddSelfTypeToSelfData(const CJson *authParam, CJson *returnToSelf)
126 {
127     int32_t userType = 0;
128     if (GetIntFromJson(authParam, FIELD_SELF_TYPE, &userType) != HC_SUCCESS) {
129         LOGE("Failed to get self userType from authParam!");
130         return HC_ERR_JSON_GET;
131     }
132     if (AddIntToJson(returnToSelf, FIELD_USER_TYPE, userType) != HC_SUCCESS) {
133         LOGE("Failed to add self userType for onFinish!");
134         return HC_ERR_JSON_FAIL;
135     }
136     return HC_SUCCESS;
137 }
138 
AddPeerTypeToSelfData(const CJson * authParam,CJson * returnToSelf)139 static int32_t AddPeerTypeToSelfData(const CJson *authParam, CJson *returnToSelf)
140 {
141     int32_t peerUserType = 0;
142     if (GetIntFromJson(authParam, FIELD_PEER_USER_TYPE, &peerUserType) != HC_SUCCESS) {
143         LOGE("Failed to get peerUserType from authParam!");
144         return HC_ERR_JSON_GET;
145     }
146     if (AddIntToJson(returnToSelf, FIELD_PEER_USER_TYPE, peerUserType) != HC_SUCCESS) {
147         LOGE("Failed to add peer peerUserType for onFinish!");
148         return HC_ERR_JSON_FAIL;
149     }
150     return HC_SUCCESS;
151 }
152 
AddSessionKeyToSelfData(const CJson * authParam,const CJson * sendToSelf,CJson * returnToSelf)153 static int32_t AddSessionKeyToSelfData(const CJson *authParam, const CJson *sendToSelf, CJson *returnToSelf)
154 {
155     int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH;
156     (void)GetIntFromJson(authParam, FIELD_KEY_LENGTH, &keyLen);
157     uint8_t *sessionKey = (uint8_t *)HcMalloc(keyLen, 0);
158     if (sessionKey == NULL) {
159         LOGE("Failed to allocate memory for sessionKey!");
160         return HC_ERR_ALLOC_MEMORY;
161     }
162     int32_t res = HC_SUCCESS;
163     do {
164         if (GetByteFromJson(sendToSelf, FIELD_SESSION_KEY, sessionKey, keyLen) != HC_SUCCESS) {
165             LOGE("Failed to get sessionKey!");
166             res = HC_ERR_JSON_GET;
167             break;
168         }
169         if (AddByteToJson(returnToSelf, FIELD_SESSION_KEY, (const uint8_t *)sessionKey, keyLen) != HC_SUCCESS) {
170             LOGE("Failed to add sessionKey for onFinish!");
171             res = HC_ERR_JSON_FAIL;
172             break;
173         }
174     } while (0);
175     (void)memset_s(sessionKey, keyLen, 0, keyLen);
176     HcFree(sessionKey);
177     sessionKey = NULL;
178     return res;
179 }
180 
PrepareDasReturnToSelfData(const CJson * authParam,const CJson * sendToSelf,CJson * returnToSelf)181 static int32_t PrepareDasReturnToSelfData(const CJson *authParam, const CJson *sendToSelf, CJson *returnToSelf)
182 {
183     int32_t res = AddGroupIdToSelfData(authParam, returnToSelf);
184     if (res != HC_SUCCESS) {
185         return res;
186     }
187     res = AddPeerUdidToSelfData(authParam, returnToSelf);
188     if (res != HC_SUCCESS) {
189         return res;
190     }
191     res = AddPeerAuthIdToSelfData(authParam, returnToSelf);
192     if (res != HC_SUCCESS) {
193         return res;
194     }
195     res = AddSelfTypeToSelfData(authParam, returnToSelf);
196     if (res != HC_SUCCESS) {
197         return res;
198     }
199     res = AddPeerTypeToSelfData(authParam, returnToSelf);
200     if (res != HC_SUCCESS) {
201         return res;
202     }
203     res = AddSessionKeyToSelfData(authParam, sendToSelf, returnToSelf);
204     if (res != HC_SUCCESS) {
205         return res;
206     }
207     return HC_SUCCESS;
208 }
209 
DasOnFinishToPeer(int64_t requestId,const CJson * out,const DeviceAuthCallback * callback)210 static int32_t DasOnFinishToPeer(int64_t requestId, const CJson *out, const DeviceAuthCallback *callback)
211 {
212     int32_t res = HC_SUCCESS;
213     CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER);
214     if (sendToPeer == NULL) {
215         LOGI("No need to transmit data to peer.");
216         return res;
217     }
218     if (AddBoolToJson(sendToPeer, FIELD_IS_DEVICE_LEVEL, false) != HC_SUCCESS) {
219         LOGE("Failed to add device level flag!");
220         return HC_ERR_JSON_ADD;
221     }
222     char *sendToPeerStr = PackJsonToString(sendToPeer);
223     if (sendToPeerStr == NULL) {
224         LOGE("Failed to pack sendToPeerStr for onTransmit!");
225         return HC_ERR_ALLOC_MEMORY;
226     }
227     if ((callback != NULL) && (callback->onTransmit != NULL)) {
228         LOGD("Begin to transmit data to peer for auth in DasOnFinishToPeer.");
229         UPDATE_PERFORM_DATA_BY_SELF_INDEX(requestId, HcGetCurTimeInMillis());
230         if (!callback->onTransmit(requestId, (uint8_t *)sendToPeerStr, (uint32_t)HcStrlen(sendToPeerStr) + 1)) {
231             LOGE("Failed to transmit data to peer!");
232             res = HC_ERR_TRANSMIT_FAIL;
233         }
234         LOGD("End to transmit data to peer for auth in DasOnFinishToPeer.");
235     }
236     FreeJsonString(sendToPeerStr);
237     return res;
238 }
239 
ReportV1UnrelatedAuthCallEvent(int64_t requestId,const CJson * authParam)240 static void ReportV1UnrelatedAuthCallEvent(int64_t requestId, const CJson *authParam)
241 {
242 #ifdef DEV_AUTH_HIVIEW_ENABLE
243     DevAuthCallEvent eventData;
244     eventData.appId = SOFTBUS_APP_ID;
245     eventData.funcName = AUTH_DEV_EVENT;
246     eventData.osAccountId = DEFAULT_OS_ACCOUNT;
247     (void)GetIntFromJson(authParam, FIELD_OS_ACCOUNT_ID, &eventData.osAccountId);
248     eventData.callResult = DEFAULT_CALL_RESULT;
249     eventData.processCode = PROCESS_AUTH_V1;
250     eventData.credType = DEFAULT_CRED_TYPE;
251     eventData.groupType = PEER_TO_PEER_GROUP;
252     eventData.executionTime = GET_TOTAL_CONSUME_TIME_BY_REQ_ID(requestId);
253     eventData.extInfo = DEFAULT_EXT_INFO;
254     DEV_AUTH_REPORT_CALL_EVENT(eventData);
255     return;
256 #endif
257     (void)requestId;
258     (void)authParam;
259     return;
260 }
261 
DasOnFinishToSelf(int64_t requestId,const CJson * authParam,const CJson * out,const DeviceAuthCallback * callback)262 static int32_t DasOnFinishToSelf(int64_t requestId, const CJson *authParam, const CJson *out,
263     const DeviceAuthCallback *callback)
264 {
265     const CJson *sendToSelf = GetObjFromJson(out, FIELD_SEND_TO_SELF);
266     if (sendToSelf == NULL) {
267         LOGE("No data to send to self for onFinish.");
268         return HC_ERR_LOST_DATA;
269     }
270     CJson *returnToSelf = CreateJson();
271     if (returnToSelf == NULL) {
272         LOGE("Create json failed!");
273         return HC_ERR_ALLOC_MEMORY;
274     }
275     int32_t res = PrepareDasReturnToSelfData(authParam, sendToSelf, returnToSelf);
276     if (res != HC_SUCCESS) {
277         LOGE("Failed to add das returnToSelf data!");
278         ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY);
279         FreeJson(returnToSelf);
280         return res;
281     }
282     char *returnStr = PackJsonToString(returnToSelf);
283     ClearSensitiveStringInJson(returnToSelf, FIELD_SESSION_KEY);
284     FreeJson(returnToSelf);
285     if (returnStr == NULL) {
286         LOGE("Failed to pack returnToSelf for onFinish!");
287         return HC_ERR_ALLOC_MEMORY;
288     }
289     if ((callback != NULL) && (callback->onFinish != NULL)) {
290         LOGD("Group auth call onFinish for account unrelated auth.");
291         UPDATE_PERFORM_DATA_BY_INPUT_INDEX(requestId, ON_FINISH_TIME, HcGetCurTimeInMillis());
292         callback->onFinish(requestId, AUTH_FORM_ACCOUNT_UNRELATED, returnStr);
293     }
294     ClearAndFreeJsonString(returnStr);
295     ReportV1UnrelatedAuthCallEvent(requestId, authParam);
296     return res;
297 }
298 
AddNonAccountPkgName(const TrustedGroupEntry * entry,CJson * paramsData)299 static int32_t AddNonAccountPkgName(const TrustedGroupEntry *entry, CJson *paramsData)
300 {
301     uint32_t groupType = entry->type;
302     if (groupType == COMPATIBLE_GROUP) {
303         if ((entry->managers).size(&(entry->managers)) == 0) {
304             LOGE("The manager size is 0!");
305             return HC_ERR_DB;
306         }
307         HcString ownerName = (entry->managers).get(&(entry->managers), 0);
308         const char *ownerNameStr = StringGet(&ownerName);
309         if (ownerNameStr == NULL) {
310             LOGE("Failed to get ownerName!");
311             return HC_ERR_DB;
312         }
313         if (AddStringToJson(paramsData, FIELD_SERVICE_PKG_NAME, ownerNameStr) != HC_SUCCESS) {
314             LOGE("Failed to add ownerName to json!");
315             return HC_ERR_JSON_FAIL;
316         }
317     } else {
318         if (AddStringToJson(paramsData, FIELD_SERVICE_PKG_NAME, GROUP_MANAGER_PACKAGE_NAME) != HC_SUCCESS) {
319             LOGE("Failed to add group manager name to json!");
320             return HC_ERR_JSON_FAIL;
321         }
322     }
323     return HC_SUCCESS;
324 }
325 
AddNonAccountAuthInfo(const TrustedDeviceEntry * localAuthInfo,const TrustedDeviceEntry * peerAuthInfo,CJson * paramsData)326 static int32_t AddNonAccountAuthInfo(const TrustedDeviceEntry *localAuthInfo, const TrustedDeviceEntry *peerAuthInfo,
327     CJson *paramsData)
328 {
329     int32_t keyLen = DEFAULT_RETURN_KEY_LENGTH;
330     (void)GetIntFromJson(paramsData, FIELD_KEY_LENGTH, &keyLen);
331     if (AddIntToJson(paramsData, FIELD_KEY_LENGTH, keyLen) != HC_SUCCESS) {
332         LOGE("Failed to add keyLen for auth!");
333         return HC_ERR_JSON_FAIL;
334     }
335     if (AddStringToJson(paramsData, FIELD_SELF_AUTH_ID, StringGet(&localAuthInfo->authId))
336         != HC_SUCCESS) {
337         LOGE("Failed to add self authId to paramsData from db!");
338         return HC_ERR_JSON_FAIL;
339     }
340     if (AddIntToJson(paramsData, FIELD_SELF_TYPE, localAuthInfo->devType) != HC_SUCCESS) {
341         LOGE("Failed to add self devType to paramsData from db!");
342         return HC_ERR_JSON_FAIL;
343     }
344     const char *peerAuthId = GetStringFromJson(paramsData, FIELD_PEER_ID_FROM_REQUEST);
345     if (peerAuthId == NULL) {
346         peerAuthId = StringGet(&peerAuthInfo->authId);
347     }
348     if (AddStringToJson(paramsData, FIELD_PEER_AUTH_ID, peerAuthId) != HC_SUCCESS) {
349         LOGE("Failed to add peer authId to paramsData!");
350         return HC_ERR_JSON_FAIL;
351     }
352     if (AddIntToJson(paramsData, FIELD_PEER_USER_TYPE, peerAuthInfo->devType) != HC_SUCCESS) {
353         LOGE("Failed to add peer devType to paramsData from db!");
354         return HC_ERR_JSON_FAIL;
355     }
356     return HC_SUCCESS;
357 }
358 
FillNonAccountAuthInfo(int32_t osAccountId,const TrustedGroupEntry * entry,const TrustedDeviceEntry * localAuthInfo,CJson * paramsData)359 static int32_t FillNonAccountAuthInfo(int32_t osAccountId, const TrustedGroupEntry *entry,
360     const TrustedDeviceEntry *localAuthInfo, CJson *paramsData)
361 {
362     int32_t res;
363     const char *groupId = StringGet(&entry->id);
364     TrustedDeviceEntry *peerAuthInfo = CreateDeviceEntry();
365     if (peerAuthInfo == NULL) {
366         LOGE("Failed to allocate devEntry memory for peerAuthInfo!");
367         return HC_ERR_ALLOC_MEMORY;
368     }
369     const char *peerUdid = GetStringFromJson(paramsData, FIELD_PEER_CONN_DEVICE_ID);
370     const char *peerAuthId = GetStringFromJson(paramsData, FIELD_PEER_ID_FROM_REQUEST);
371     if (peerAuthId == NULL) {
372         peerAuthId = GetStringFromJson(paramsData, FIELD_PEER_AUTH_ID);
373     }
374     if (peerUdid != NULL) {
375         res = GaGetTrustedDeviceEntryById(osAccountId, peerUdid, true, groupId, peerAuthInfo);
376     } else if (peerAuthId != NULL) {
377         res = GaGetTrustedDeviceEntryById(osAccountId, peerAuthId, false, groupId, peerAuthInfo);
378     } else {
379         LOGE("Invalid input, both peer udid and peer authId are null!");
380         res = HC_ERR_NULL_PTR;
381     }
382     do {
383         if (res != HC_SUCCESS) {
384             LOGE("Failed to get peer device info from database!");
385             break;
386         }
387         res = AddNonAccountPkgName(entry, paramsData);
388         if (res != HC_SUCCESS) {
389             LOGE("Failed to add pkg name to paramsData!");
390             break;
391         }
392         res = AddNonAccountAuthInfo(localAuthInfo, peerAuthInfo, paramsData);
393         if (res != HC_SUCCESS) {
394             LOGE("Failed to add device auth info for non-account group!");
395             break;
396         }
397     } while (0);
398     DestroyDeviceEntry(peerAuthInfo);
399     return res;
400 }
401 
CombineDasServerConfirmParams(const CJson * confirmationJson,CJson * dataFromClient)402 static int32_t CombineDasServerConfirmParams(const CJson *confirmationJson, CJson *dataFromClient)
403 {
404     bool isClient = false;
405     if (AddBoolToJson(dataFromClient, FIELD_IS_CLIENT, isClient) != HC_SUCCESS) {
406         LOGE("Failed to combine server param for isClient!");
407         return HC_ERR_JSON_FAIL;
408     }
409     const char *pkgName = GetStringFromJson(confirmationJson, FIELD_SERVICE_PKG_NAME);
410     if (pkgName != NULL) {
411         if (AddStringToJson(dataFromClient, FIELD_SERVICE_PKG_NAME, pkgName) != HC_SUCCESS) {
412             LOGE("Failed to combine server param for pkgName!");
413             return HC_ERR_JSON_FAIL;
414         }
415     }
416 
417     const char *peerUdid = GetStringFromJson(confirmationJson, FIELD_PEER_CONN_DEVICE_ID);
418     if (peerUdid != NULL) {
419         if (AddStringToJson(dataFromClient, FIELD_PEER_CONN_DEVICE_ID, peerUdid) != HC_SUCCESS) {
420             LOGE("Failed to combine server param for peerUdid!");
421             return HC_ERR_JSON_FAIL;
422         }
423     }
424     const char *peerAuthId = GetStringFromJson(confirmationJson, FIELD_PEER_AUTH_ID);
425     if (peerAuthId != NULL) {
426         if (AddStringToJson(dataFromClient, FIELD_PEER_ID_FROM_REQUEST, peerAuthId) != HC_SUCCESS) {
427             LOGE("Failed to combine server param for peerAuthId!");
428             return HC_ERR_JSON_FAIL;
429         }
430     }
431     return HC_SUCCESS;
432 }
433 
GetAuthParamsVecForServer(const CJson * dataFromClient,ParamsVecForAuth * authParamsVec)434 static int32_t GetAuthParamsVecForServer(const CJson *dataFromClient, ParamsVecForAuth *authParamsVec)
435 {
436     LOGI("Begin get non-account auth params for server.");
437     int32_t osAccountId = ANY_OS_ACCOUNT;
438     if (GetIntFromJson(dataFromClient, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
439         LOGE("Failed to get os accountId from dataFromClient!");
440         return HC_ERR_JSON_GET;
441     }
442     int32_t res = GetAuthParamsVec(osAccountId, dataFromClient, authParamsVec);
443     if (res != HC_SUCCESS) {
444         LOGE("Failed to get non-account auth params!");
445     }
446     return res;
447 }
448 
OnDasFinish(int64_t requestId,const CJson * authParam,const CJson * out,const DeviceAuthCallback * callback)449 static void OnDasFinish(int64_t requestId, const CJson *authParam, const CJson *out,
450     const DeviceAuthCallback *callback)
451 {
452     LOGI("Begin call onFinish for non-account auth.");
453     if (DasOnFinishToPeer(requestId, out, callback) != HC_SUCCESS) {
454         LOGE("Failed to send data to peer when auth finished!");
455         return;
456     }
457     if (ReturnSessionKey(requestId, out, callback) != HC_SUCCESS) {
458         LOGE("Failed to return session key when auth finished!");
459         return;
460     }
461     if (DasOnFinishToSelf(requestId, authParam, out, callback) != HC_SUCCESS) {
462         LOGE("Failed to send data to self when auth finished!");
463         return;
464     }
465     LOGI("Call onFinish for non-account auth successfully.");
466 }
467 
GetAccountUnrelatedGroupAuth(void)468 BaseGroupAuth *GetAccountUnrelatedGroupAuth(void)
469 {
470     return (BaseGroupAuth *)&g_nonAccountGroupAuth;
471 }
472