freeradius (MySQL config) adding custom attributes to the reply-item - attributes

I've run into a dead end while trying to set up customized attributes as a reply item (I want custom information added to the "access accept" packet).
While trying to achieve this I came across this entry:
# If you want to add entries to the dictionary file,
# which are NOT going to be placed in a RADIUS packet,
# add them to the 'dictionary.local' file.
#
# The numbers you pick should be between 3000 and 4000.
# These attributes will NOT go into a RADIUS packet.
#
# If you want that, you will need to use VSAs. This means
# requesting allocation of a Private Enterprise Code from
# http://iana.org. We STRONGLY suggest doing that only if
# you are a vendor of RADIUS equipment.
#
# See RFC 6158 for more details.
# http://ietf.org/rfc/rfc6158.txt
So I understand how the usual approach should be.
However my infrastructure is set up in stages and the radius server in question is already placed on the "inside", so I don't see why I shouldn't be able to set or overwrite unused attributes on both ends of this second internal authentication step.
Googleing around I found several threads on how to set this type of thing up with a users-file based approach on 1.x versions of Freeradius, not so much for any of the newer releases.
Is what I'm proposing still possible with freeradius-server-3.0.10 ?
And if so, how should I go about implementing this?
Current state:
I've added my attribute "faculty" to the dictionary (mapping the set integer from the DB to a string set in directory ie. Ei & MECH) and the respective DB, causing the radius server to find and evaluate the attribute set in "radreply" (here: := MECH) and "radgroupreply" (here += EI).
...
rlm_sql (sql1): Reserved connection (5)
(1) sql1: EXPAND SELECT id, username, attribute, value, op FROM radcheck WHERE username = '%{SQL-User-Name}' AND active > '0' AND active < '3' ORDER BY id(1) sql1: --> SELECT id, username, attribute, value, op FROM radcheck WHERE username = '*username*' AND active > '0' AND active < '3' ORDER BY id
(1) sql1: Executing select query: SELECT id, username, attribute, value, op FROM radcheck WHERE username = '*username*' AND active > '0' AND active < '3'ORDER BY id
(1) sql1: User found in radcheck table
(1) sql1: Conditional check items matched, merging assignment check items
(1) sql1: Cleartext-Password := "*password*"
(1) sql1: EXPAND SELECT id, username, attribute, value, op FROM radreply WHERE username = '%{SQL-User-Name}' ORDER BY id
(1) sql1: --> SELECT id, username, attribute, value, op FROM radreply WHERE username = '*username*' ORDER BY id
(1) sql1: Executing select query: SELECT id, username, attribute, value, op FROM radreply WHERE username = '*username*' ORDER BY id
(1) sql1: User found in radreply table, merging reply items
(1) sql1: faculty := MECH
(1) sql1: EXPAND SELECT groupname FROM radusergroup WHERE username = '%{SQL-User-Name}' ORDER BY priority
(1) sql1: --> SELECT groupname FROM radusergroup WHERE username = '*username*' ORDER BY priority
(1) sql1: Executing select query: SELECT groupname FROM radusergroup WHERE username = '*username*' ORDER BY priority
(1) sql1: User found in the group table
(1) sql1: EXPAND SELECT id, groupname, attribute, Value, op FROM radgroupcheck WHERE groupname = '%{sql1-SQL-Group}' ORDER BY id
(1) sql1: --> SELECT id, groupname, attribute, Value, op FROM radgroupcheck WHERE groupname = 'vid100' ORDER BY id
(1) sql1: Executing select query: SELECT id, groupname, attribute, Value, op FROM radgroupcheck WHERE groupname = 'vid100' ORDER BY id
(1) sql1: Group "vid100": Conditional check items matched
(1) sql1: Group "vid100": Merging assignment check items
(1) sql1: EXPAND SELECT id, groupname, attribute, value, op FROM radgroupreply WHERE groupname = '%{sql1-SQL-Group}' ORDER BY id
(1) sql1: --> SELECT id, groupname, attribute, value, op FROM radgroupreply WHERE groupname = 'vid100' ORDER BY id
(1) sql1: Executing select query: SELECT id, groupname, attribute, value, op FROM radgroupreply WHERE groupname = 'vid100' ORDER BY id
(1) sql1: Group "vid100": Merging reply items
(1) sql1: Tunnel-Type = VLAN
(1) sql1: Tunnel-Medium-Type = IEEE-802
(1) sql1: Tunnel-Private-Group-Id = "100"
(1) sql1: faculty += EI
rlm_sql (sql1): Released connection (5)
...
The keen observer will also notice some changes to the "radcheck" query, but this change is not related to the topic at hand.
So the Server gets the information, however I've not found a way to include it to the reply yet.
(1) Sent Access-Accept Id 81 from **IP-Radius-server**:*port* to **IP-supplicant**:*port* length 0
(1) Tunnel-Type = VLAN
(1) Tunnel-Medium-Type = IEEE-802
(1) Tunnel-Private-Group-Id = "100"
(1) Finished request
Any help or pointers would be appreciated :)
Felix

To anyone having similar problems.
I've come up with a workaround that works for me.
As described above it really is a lot of fuss to build a custom attribute.
What you can use though, is attribute 18 (Reply-Message) to convey information.
I went about this by adding to: .../raddb/sites-available/default in the "post-auth" section.
if (&reply:faculty && &request:NAS-IP-Address == *IP-WEBSERVER*) {
update reply {
Reply-Message += "Faculty: %{reply:faculty}"
}
}
Which adds "faculty" information if it can be found in either the radreply or the radgroupreply if and only if the supplication comes via the sepcified "webserver". Using the freeradius operator arithmetic you can also weight the reply (for me: radreply := radgroupreply +=).
This works well for freeradius3.0.10.
I consider this thread closed - Felix

You need to define your custom attribute as a VSA (Vendor specific attribute). Attributes above 255 in the standard RADIUS dictionary will not be encoded in proxied requests, or in replies, that is because the attribute field is only 1 byte wide.
If you want to do it properly you'll need to request an IANA PEN (Private Enterprise Number) http://pen.iana.org/pen/PenApplication.page for your organisation (after checking there isn't already one assigned http://www.iana.org/assignments/enterprise-numbers/enterprise-numbers).
You can then define your own vendor dictionary, and add your own attributes with numbers between 1-255.
Here's a nice short one you can use as an example: https://github.com/FreeRADIUS/freeradius-server/blob/v3.1.x/share/dictionary.bt
You don't need a separate file for your vendor dictionary, you just need to copy the relevant lines into raddb/dictionary.
If you don't care about doing it properly, look through the PEN assignments to find a defunct company and use their PEN.

Related

How can I make a demand command loop?

I have a command named demand and need to make a limit to amounts per user. There are roles in the server named "team_role" and then there's also "2 demands", "1 demand", and "0 demands". After the user demands, I need it to role them down a demand until eventually, they hit 0. Once they hit 0, it should send them a message saying they can't demand. Here's my code for one of the teams (the Dallas Cowboys).
#bot.command(aliases=["<:DallasCowboys:788796627161710592>"])
#commands.has_any_role("Dallas Cowboys")
async def t(ctx):
guild = bot.get_guild(766292887914151949)
role_name = discord.utils.get(guild.roles, name='Free Agent')
role = discord.utils.get(guild.roles, name='Dallas Cowboys')
embed = discord.Embed()
embed.add_field(name="<a:CheckMark:768095274949935146> Successful Demand", value=f"{ctx.author.mention} has demanded from the <:DallasCowboys:788796627161710592>")
await ctx.send(embed=embed)
await ctx.author.add_roles(role_name)
await ctx.author.remove_roles(role)
Since you said I can just provide the logic:
Create a means of persistently storing the data, whether that be
json file or a database.
a) If you choose the json file, the file will consist of key value
pairs of user ids to number of demands remaining. For example, the
file might look something like this:
{ "UserDemandsRemaining" : { 12345 : 2, 45678: 1, 09876: 0 } }
b) If you choose to use to use a SQL database, create a table called
UserDemandsRemaining with two fields: UserId and
DemandsRemaining. The primary key would be UserId.
Each time a user makes a demand, you will check how many remaining
demands the user has.
If there is no matching UserId stored:
a) If you chose to use a json file, and there is no matching key in the json value associated with the UserDemandsRemaining key, then create a key-value pair with the key as the UserId that made the demand, and the value as 3.
b) If you chose to use a SQL db, and there is no matching UserId matching the UserId that made the demand in the UserDemandsRemaining table of the database, then insert a row into the table containing the UserId that made the demand and a DemandsRemaining value of 3.
Since the user isn't stored, we know that they have not yet made any demands. Execute the demand. Then decrement the `DemandsRemaining` by 1.
Else if there is a matching UserId:
if DemandsRemaining > 0:
#Execute the command. Decrement `DemandsRemaining` by 1.
else:
#Notify the user that they have no more remaining demands.
In order to reset the number of demands each person has remaining,
just set the value pair associated with the users in the json file
or the DemandsRemaining in the table to 3 for everyone.

Lotus Notes NAB - Adding a field

I have a project that I need to put an Internet Address and also add a new field called ShortName for all groups in the Notes NAB.
I am able to put the values and save the document , I tried with a doc.save and a computewithform. This is the Group form.
After the change, people in that group are no longer able to access the application.
Do you have an idea what I am doing wrong ?
User A is in group XYZ.
I added internetaddress xyz.com and a shortname text field xyzmigration
Application A is having an ACL with the group XYZ as editor. When User A tries to open the Application A, he get a not authorize. If I delete both values, User A is able to open the database.
Thanks for your help
$ServerAccess view validates Group documents and omits any Groups that has Shortname field present.
Normunds has the correct answer, but I want to add a suggestion: create a new group instead of modifying the existing group. I.e., if the group is "MyGroup", create a group named "MyGroup_Extended" and set it up with
Shortname = the value that you want
InternetAddress = the value that you want
Members = "MyGroup"
That way, you leave MyGroup untouched, but you still have a modified group document with the additional information added and the same member list.
And another thing: In order to make those groups that you already altered functional again, you should run a simple agent against all of the groups that does this:
FIELD ShortName := #DeleteField;
FIELD InternetAddress := #DeleteField;
After the help of some answers that I got here. I checked the view $ServerAccess. The selection formula is checking for a field Shortname and that is what was causing my problem. I will create another field name and we will be able to use this field instead of ShortName. allfields := #DocFields;
test1 := 0;
test2 := 0;
#For(i:=1; i < #Elements(allfields); i:=i+1; test1 := test1 + #If(#UpperCase(allfields[i]) = "LISTNAME";1;0));
#For(i:=1; i < #Elements(allfields); i:=i+1; test2:=test2 + #If(#UpperCase(allfields[i]) = "SHORTNAME";1;0));
SELECT (test1 < 2 & test2 = 0 &Type = "Group" & (#IsUnavailable ( GroupType)|GroupType="0" : "2":"3":"4")) & Form="Group" & #IsUnavailable($Conflict)
Thanks for your help.

SQL injection ,why should you write 0 or 1=1

In SQL injection, why should you use 0 or 1=1, isn't this automatically evaluated as 1 in boolean operation? I don't understand why we should write it that way. Can someone explain?
Thanks in advance
Because it makes the condition always true.
For example, if someone's SQL code is:
string query = "SELECT * FROM Users WHERE Password = '" + somePassword + "'";
(Username clause omitted for brevity.)
Then you can enter something like this as the password:
' OR 1 = 1;--
Which would make the resulting query:
SELECT * FROM Users WHERE Password = '' OR 1 = 1;--'
The semicolon ends the statement, and -- denotes a comment so everything thereafter is ignored. So it simplifies to:
SELECT * FROM Users WHERE Password = '' OR 1 = 1
This will match all records in the table. Always. Because 1 = 1 is always true. Depending on how the application handles this response, you may be logged in. Perhaps even as the first user in the table, which is likely to be the admin user.
For SQL-injectable code, it's basically a universal password. (Provided you guess a correct username, which isn't difficult.)
Edit: I just noticed the 0 part of your question as well. This would be used when you expect the injected value to be looking for a number rather than a string. For example, consider a similar SQL statement:
string query = "SELECT * FROM Users WHERE Id = " + someID;
The leading 0 in the injected value prevents a syntax error. So the resulting query would be:
SELECT * FROM Users WHERE Id = 0 OR 1 = 1
Same concept as above. This will match all records every time.
Here is a brief explanation for this:-
select title, text from news where id=$id
In the example above the variable $id contains user-supplied data, while the remainder is the SQL static part supplied by the programmer; making the SQL statement dynamic.
Because the way it was constructed, the user can supply crafted input trying to make the original SQL statement execute further actions of the user's choice. The example below illustrates the user-supplied data β€œ10 or 1=1”, changing the logic of the SQL statement, modifying the WHERE clause adding a condition β€œor 1=1”.
select title, text from news where id=10 or 1=1
so the query will still get executed

Determining Current User for Generic Inquiry

I want to create a number of generic inquiries that lists the leads or other items for the user that's currently logged into Acumatica.
The answer to the question [Current logged in user for GI / Reports in 4.2] (Current logged in user for GI / Reports in 4.2) does not work for me in a generic inquiry. It works as described for reports.
We are using Acumatica 5.20.1757.
Using only PX.Data.AccessInfo in the generic inquiry results in the error: Sequence contains no elements. Using it in a cross join with another table gives: "Invalid object name: AccessInfo. What don't I understand/know?
While the answer above worked quite well, this gets rid of the need to select a name and configure access rights. The following example uses leads.
Provide values for Site Map Title and Site Map Location, found just below the Inquiry Title field/
On the Tables tab, select PX.Data.AccessInfo, PX.Objects.CR.Contact, PX.Object.EP.EPEmployee, PX.SM.LoginTrace, and PX.SM.Users. Accept the defaults for the alias, which will populate once you leave the line.
On the Relations tab:
a) set, Active checked, Parent Table Contact Join Type ** Left **Child Table EPEmployee, Parent Field ownerID Condition Equals Child Field pKID
b) set Active checked, Parent Table Users Join Type ** Inner **Child Table EPEmployee, Parent Field contactID Condition Equals Child Field defContactID
c) set Active checked, Parent Table Users Join Type ** Inner **Child Table LoginTrace, Parent Field username Condition Equals Child Field username
On the Parameters tab set Name ** to Username, **Schema Field to AccessInfo.UserName and **Display Name ** to User Name. Active should not be checked unless you want to check the value of the field.
9 lines were set to meet my specific conditions. Here they are.
a) Active True, Start Brackets (, Data Field Users.IsOnline Condition Equals, From Schema True, Value 1 True, End Brackets , Operator And
b) Active True, Start Brackets , Data Field LoginTrace.ScreenID Condition Equals, From Schema False, Value 1 GI000009 (yours might be different), End Brackets , Operator And
c) Active False, Start Brackets , Data Field LoginTrace.Date Condition Equals, From Schema False, Value 1 Now(), End Brackets ), Operator And
d) Active True, Start Brackets , Data Field Users.UserName Condition Equals, From Schema False, Value 1 =[LoginTrace.Username], End Brackets , Operator And
e) Active False, Start Brackets , Data Field LoginTrace.Username Condition Equals, From Schema False, Value 1 =[EPEmployee.UserID], End Brackets , Operator And
f) Active True, Start Brackets ((, Data Field Contact.ContactType Condition Equals, From Schema FALSE, Value 1 LD, End Brackets , Operator Or
g) Active True, Start Brackets , Data Field Contact.ContactType Condition Equals, From Schema FALSE, Value 1 PN, End Brackets ), Operator And
g) Active True, Start Brackets , Data Field Contact.Status Condition Equals, From Schema True, Value 1 Converted, End Brackets , Operator Or
h) Active True, Start Brackets , Data Field Contact.Status Condition Equals, From Schema True, Value 1 Open, End Brackets ), Operator Or
On the Grouping tab, set Active to True, and Data Field to Contact.ContactID
Sort order, results grid, and Entry point are up to you.
Notes: I found this GI failed in a different query where the LoginTrace.ScreenID condition was left out. It was not tried with left joins for the inner joins, but should have worked.
I just designed a generic inquiry that lists all sales orders created by the user currently logged in for a customer that uses 4.2 of Acumatica. Here are the steps.
At the Tables tab of the Generic Inquiry screen, 2 tables need to be added in addition of the other desired tables (in this example, SO.SOOrder): Data.AccessInfo and SM.Users.
At the Relations tab, the table relation should be created between the desired tables and SM.Users. The Join Type must be Left. Ex.: SOOrder Left Join Users.
The relation must be established using the pKID field of the Users table. Ex.: SOOrder.CreatedByID Equals Users.pKID.
At the Parameters tab, add a line and give it a name like UserName. The Schema Field would then be AccessInfo.UserName. The From Schema option must be activated.
At the Conditions tab, the Data Field Users.UserName Equals the parameter added in #4 as the value.
If you do not want the user to change the default username defined as parameter, make sure to review the access rights of that field in the different roles.

Query Trac for all tickets related to a user

How do I query for all trac tickets related to a user. i.e. all tickets for which the tickets were once assigned, assigned now, created , etc etc
Create custom queries to the ticket_change table. Some SQL required. For assigned once/now, look for rows where field='owner', newvalue column contains the user name the ticket was assigned to. For created tickets, just query by reporter in the ticket table.
Example:
SELECT p.value AS __color__,
id AS ticket, summary, component, version, milestone,
t.type AS type, priority, t.time AS created,
changetime AS _changetime, description AS _description,
reporter AS _reporter
FROM ticket t, enum p, ticket_change c
WHERE p.name = t.priority AND p.type = 'priority'
AND c.field = 'owner'
AND c.newvalue = '$USER'
AND c.ticket = t.id
ORDER BY p.value, milestone, t.type, t.time
You can express this with a TraqQuery expression. E.g. if you want the columns id, summary and status to show up and query all the tickets for the currently logged in user ($USER) then use the following query.
query:?col=id
&
col=summary
&
col=status
&
owner=$USER
However this query assumes that the owner hasn't been the same during the lifetime of a ticket (since ownership can be changed).
If you want a specific user then replace $USER with the actual username. Also if you're using the Agilo plugin you can easily create new queries on the fly via the web-UI. This is done by looking at a report and adding filters to the report.

Resources