Quellcode durchsuchen

adding usernamepassword auth to client, fixing a username/pass struct bug in the server

Stasik0 vor 9 Jahren
Ursprung
Commit
d81279feb0
6 geänderte Dateien mit 74 neuen und 15 gelöschten Zeilen
  1. 2 1
      examples/client.c
  2. 13 0
      include/ua_client.h
  3. 1 1
      include/ua_server.h
  4. 43 10
      src/client/ua_client.c
  5. 10 0
      src/client/ua_client_internal.h
  6. 5 3
      src/server/ua_server.c

+ 2 - 1
examples/client.c

@@ -46,7 +46,8 @@ int main(int argc, char *argv[]) {
     UA_Array_delete(endpointArray,endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
 
     //connect to a server
-    retval = UA_Client_connect(client, UA_ClientConnectionTCP, "opc.tcp://localhost:16664");
+    //anonymous connect would be: retval = UA_Client_connect_username(client, UA_ClientConnectionTCP, "opc.tcp://localhost:16664");
+    retval = UA_Client_connect_username(client, UA_ClientConnectionTCP, "opc.tcp://localhost:16664", "user1", "password");
 
     if(retval != UA_STATUSCODE_GOOD) {
         UA_Client_delete(client);

+ 13 - 0
include/ua_client.h

@@ -78,6 +78,19 @@ UA_Client_getEndpoints(UA_Client *client, UA_ConnectClientConnection connectFunc
 UA_StatusCode UA_EXPORT
 UA_Client_connect(UA_Client *client, UA_ConnectClientConnection connFunc, const char *endpointUrl);
 
+/**
+ * start a connection to the selected server
+ *
+ * @param client to use
+ * @param connection function. You can use ClientNetworkLayerTCP_connect from examples/networklayer_tcp.h
+ * @param endpointURL to connect (for example "opc.tcp://localhost:16664")
+ * @param username
+ * @param password
+ * @return Indicates whether the operation succeeded or returns an error code
+ */
+UA_StatusCode UA_EXPORT
+UA_Client_connect_username(UA_Client *client, UA_ConnectClientConnection connFunc, const char *endpointUrl, const char *username, const char *password);
+
 /**
  * close a connection to the selected server
  *

+ 1 - 1
include/ua_server.h

@@ -54,7 +54,7 @@ typedef struct {
     UA_Boolean enableAnonymousLogin;
     UA_Boolean enableUsernamePasswordLogin;
     size_t usernamePasswordLoginsSize;
-    UA_UsernamePasswordLogin usernamePasswordLogins[];
+    UA_UsernamePasswordLogin* usernamePasswordLogins;
 } UA_ServerConfig;
 
 extern UA_EXPORT const UA_ServerConfig UA_ServerConfig_standard;

+ 43 - 10
src/client/ua_client.c

@@ -26,6 +26,10 @@ static void UA_Client_init(UA_Client* client, UA_ClientConfig config, UA_Logger
     UA_String_init(&client->endpointUrl);
     client->requestId = 0;
 
+    client->authenticationMethod = UA_CLIENTAUTHENTICATION_NONE;
+    UA_String_init(&client->username);
+    UA_String_init(&client->password);
+
     UA_NodeId_init(&client->authenticationToken);
     client->requestHandle = 0;
 
@@ -56,6 +60,10 @@ static void UA_Client_deleteMembers(UA_Client* client) {
     if(client->endpointUrl.data)
         UA_String_deleteMembers(&client->endpointUrl);
     UA_UserTokenPolicy_deleteMembers(&client->token);
+    if(client->username.data)
+        UA_String_deleteMembers(&client->username);
+    if(client->password.data)
+           UA_String_deleteMembers(&client->password);
 #ifdef UA_ENABLE_SUBSCRIPTIONS
     UA_Client_NotificationsAckNumber *n, *tmp;
     LIST_FOREACH_SAFE(n, &client->pendingNotificationsAcks, listEntry, tmp) {
@@ -315,20 +323,29 @@ static UA_StatusCode ActivateSession(UA_Client *client) {
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 600000;
 
-    UA_AnonymousIdentityToken identityToken;
-    UA_AnonymousIdentityToken_init(&identityToken);
-    UA_String_copy(&client->token.policyId, &identityToken.policyId);
-
     //manual ExtensionObject encoding of the identityToken
-    request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
-    request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN];
-    request.userIdentityToken.content.decoded.data = &identityToken;
+    if(client->authenticationMethod == UA_CLIENTAUTHENTICATION_NONE){
+        UA_AnonymousIdentityToken* identityToken = UA_malloc(sizeof(UA_AnonymousIdentityToken));
+        UA_AnonymousIdentityToken_init(identityToken);
+        UA_String_copy(&client->token.policyId, &identityToken->policyId);
+        request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
+        request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN];
+        request.userIdentityToken.content.decoded.data = identityToken;
+    }else{
+        UA_UserNameIdentityToken* identityToken = UA_malloc(sizeof(UA_UserNameIdentityToken));
+        UA_UserNameIdentityToken_init(identityToken);
+        UA_String_copy(&client->token.policyId, &identityToken->policyId);
+        UA_String_copy(&client->username, &identityToken->userName);
+        UA_String_copy(&client->password, &identityToken->password);
+        request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
+        request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN];
+        request.userIdentityToken.content.decoded.data = identityToken;
+    }
 
     UA_ActivateSessionResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
                         &response, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
 
-    UA_AnonymousIdentityToken_deleteMembers(&identityToken);
     UA_ActivateSessionRequest_deleteMembers(&request);
     UA_ActivateSessionResponse_deleteMembers(&response);
     return response.responseHeader.serviceResult; // not deleted
@@ -391,8 +408,15 @@ static UA_StatusCode EndpointsHandshake(UA_Client *client) {
         /* look for a user token policy with an anonymous token */
         for(size_t j = 0; j < endpoint->userIdentityTokensSize; ++j) {
             UA_UserTokenPolicy* userToken = &endpoint->userIdentityTokens[j];
-            if(userToken->tokenType != UA_USERTOKENTYPE_ANONYMOUS)
-                continue;
+            //anonymous authentication
+            if(client->authenticationMethod == UA_CLIENTAUTHENTICATION_NONE){
+                if(userToken->tokenType != UA_USERTOKENTYPE_ANONYMOUS)
+                    continue;
+            }else{
+            //username authentication
+                if(userToken->tokenType != UA_USERTOKENTYPE_USERNAME)
+                    continue;
+            }
             tokenFound = true;
             UA_UserTokenPolicy_copy(userToken, &client->token);
             break;
@@ -537,6 +561,15 @@ UA_Client_getEndpoints(UA_Client *client, UA_ConnectClientConnection connectFunc
     return retval;
 }
 
+UA_StatusCode UA_Client_connect_username(UA_Client *client, UA_ConnectClientConnection connFunc,
+                                                 const char *endpointUrl, const char *username, const char *password){
+    client->authenticationMethod=UA_CLIENTAUTHENTICATION_USERNAME;
+    client->username = UA_STRING_ALLOC(username);
+    client->password = UA_STRING_ALLOC(password);
+    return UA_Client_connect(client, connFunc, endpointUrl);
+}
+
+
 UA_StatusCode UA_Client_connect(UA_Client *client, UA_ConnectClientConnection connectFunc,
                                 const char *endpointUrl) {
     if(client->state == UA_CLIENTSTATE_CONNECTED)

+ 10 - 0
src/client/ua_client_internal.h

@@ -52,6 +52,11 @@ typedef enum {
     UA_CLIENTSTATE_ERRORED
 } UA_Client_State;
 
+typedef enum {
+    UA_CLIENTAUTHENTICATION_NONE,
+    UA_CLIENTAUTHENTICATION_USERNAME
+} UA_Client_Authentication;
+
 struct UA_Client {
     /* State */ //maybe it should be visible to user
     UA_Client_State state;
@@ -62,6 +67,11 @@ struct UA_Client {
     UA_String endpointUrl;
     UA_UInt32 requestId;
 
+    /* Authentication */
+    UA_Client_Authentication authenticationMethod;
+    UA_String username;
+    UA_String password;
+
     /* Session */
     UA_UserTokenPolicy token;
     UA_NodeId sessionId;

+ 5 - 3
src/server/ua_server.c

@@ -16,6 +16,10 @@
 #define UA_STRING_STATIC(s) {sizeof(s)-1, (UA_Byte*)s}
 #define UA_STRING_STATIC_NULL {0, NULL}
 
+UA_UsernamePasswordLogin usernamePasswords[2] =
+{ { UA_STRING_STATIC("user1"), UA_STRING_STATIC("password") },
+  { UA_STRING_STATIC("uset2"), UA_STRING_STATIC("password1") } };
+
 const UA_ServerConfig UA_ServerConfig_standard = {
     .nThreads = 1,
     .logger = NULL,
@@ -43,9 +47,7 @@ const UA_ServerConfig UA_ServerConfig_standard = {
 
     .enableAnonymousLogin = true,
     .enableUsernamePasswordLogin = true,
-    .usernamePasswordLogins =
-    { { UA_STRING_STATIC("user1"), UA_STRING_STATIC("password") },
-      { UA_STRING_STATIC("uset2"), UA_STRING_STATIC("password1") } },
+    .usernamePasswordLogins = usernamePasswords,
     .usernamePasswordLoginsSize = 2
 };